shiro权限管理框架学习
一、權限框架簡介
基本上涉及到用戶參與的系統都要進行權限管理,權限管理屬于系統安全的范疇,權限管理實現對用戶訪問系統的控制,按照安全規則或者安全策略控制用戶可以訪問而且只能訪問自己被授權的資源。權限管理包括用戶身份認證和授權兩部分,簡稱認證授權。對于需要訪問控制的資源用戶首先經過身份認證,認證通過后用戶具有該資源的訪問權限方可訪問。
二、shiro介紹
Shiro是apache旗下一個開源框架,它將軟件系統的安全認證相關的功能抽取出來,實現用戶身份認證,權限授權、加密、會話管理等功能,組成了一個通用的安全認證框架。
三、shiro架構
四、shiro架構中核心組件
4.1 Subject
Subject即主體,外部應用與subject進行交互,subject記錄了當前操作用戶,將用戶的概念理解為當前操作的主體,可能是一個通過瀏覽器請求的用戶,也可能是一個運行的程序。Subject在shiro中是一個接口,接口中定義了很多認證授相關的方法,外部程序通過subject進行認證授,而subject是通過SecurityManager安全管理器進行認證授權
4.2 SecurityManager
SecurityManager即安全管理器,對全部的subject進行安全管理,它是shiro的核心,負責對所有的subject進行安全管理。通過SecurityManager可以完成subject的認證、授權等,實質上SecurityManager是通過Authenticator進行認證,通過Authorizer進行授權,通過SessionManager進行會話管理等。
SecurityManager是一個接口,繼承了Authenticator, Authorizer, SessionManager這三個接口。
4.3 Authenticator
Authenticator即認證器,對用戶身份進行認證,Authenticator是一個接口,shiro提供ModularRealmAuthenticator實現類,通過ModularRealmAuthenticator基本上可以滿足大多數需求,也可以自定義認證器。
4.4 Authorizer
Authorizer即授權器,用戶通過認證器認證通過,在訪問功能時需要通過授權器判斷用戶是否有此功能的操作權限。
4.5 realm
Realm即領域,相當于datasource數據源,securityManager進行安全認證需要通過Realm獲取用戶權限數據,比如:如果用戶身份數據在數據庫那么realm就需要從數據庫獲取用戶身份信息。
注意:不要把realm理解成只是從數據源取數據,在realm中還有認證授權校驗的相關的代碼。
4.6 sessionManager
sessionManager即會話管理,shiro框架定義了一套會話管理,它不依賴web容器的session,所以shiro可以使用在非web應用上,也可以將分布式應用的會話集中在一點管理,此特性可使它實現單點登錄。
4.7 SessionDAO
SessionDAO即會話dao,是對session會話操作的一套接口,比如要將session存儲到數據庫,可以通過jdbc將會話存儲到數據庫。
4.8 CacheManager
CacheManager即緩存管理,將用戶權限數據存儲在緩存,這樣可以提高性能。
4.9 Cryptography
Cryptography即密碼管理,shiro提供了一套加密/解密的組件,方便開發。比如提供常用的散列、加/解密等功能。
五、springboot+shiro+mybatis實現動態權限管理
5.1 創建ShiroConfig
package com.lcy.demo.shiro;import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;import java.util.LinkedHashMap; import java.util.Map;@Configuration public class ShiroConfig {//創建一個ShiroFilterFactoryBean@Beanpublic ShiroFilterFactoryBean getshiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();//設置安全管理器shiroFilterFactoryBean.setSecurityManager(securityManager);//shiro的內置過濾器/*** shiro內置過濾器,可以實現權限相關的攔截器* 常用的過濾器:* anon:無需認證(登錄)可以訪問* authc:必須認證才可以訪問* User:如果使用rememberMe的功能可以直接訪問* perms: 該資源必須得到資源權限才可以訪問* role:該資源必須得到角色權限才可以直接訪問*///進行攔截Map<String, String> filtermap = new LinkedHashMap<String, String>();// filtermap.put("/add", "authc"); // filtermap.put("/update", "authc");// 無需驗證filtermap.put("/test", "anon");// 放行login.html頁面filtermap.put("/login", "anon");//授權攔截器 當授權被攔截后 shiro會自動跳到未授權的頁面filtermap.put("/add", "perms[user:add]");filtermap.put("/update", "perms[user:update]");// 使用通配的方式進行攔截(同一目錄下的靜態資源)filtermap.put("/*", "authc");shiroFilterFactoryBean.setLoginUrl("/toLogin"); // 設置未授權提示的頁面shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth");shiroFilterFactoryBean.setFilterChainDefinitionMap(filtermap);return shiroFilterFactoryBean;}//創建一個DefaultWebSecuritManager@Bean(name = "securityManager")public DefaultWebSecurityManager getdefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();//關聯RealmsecurityManager.setRealm(userRealm);return securityManager;}//創建Realm@Bean(name = "userRealm")public UserRealm getRealm() {return new UserRealm();} }5.2 自定義UserRealm
package com.lcy.demo.shiro;import com.lcy.demo.Service.UserService; import com.lcy.demo.pojo.User; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired;/*** shiro的兩大核心 認證和授權*/ public class UserRealm extends AuthorizingRealm {/*** 執行授權邏輯** @param principalCollection* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("執行授權邏輯");SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();// 添加資源的授權字符串 // info.addStringPermission("user:add");// 到數據庫查詢當前登錄用戶的授權字符串 // 獲取當前的用戶Subject subject = SecurityUtils.getSubject();User user = (User) subject.getPrincipal();System.out.println(user.getId());User dbUser = userService.findById(user.getId());info.addStringPermission(dbUser.getPerms());return info;}@Autowiredprivate UserService userService;/*** 執行認證邏輯** @param authenticationToken* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {System.out.println("執行認證邏輯");// 編寫shiro的認證邏輯 判斷用戶名和密碼UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;User user = userService.findByName(token.getUsername());if (user == null) {//用戶名不存在return null;//shiro底層會拋出UnknownAccountException} // 判斷密碼return new SimpleAuthenticationInfo(user, user.getPassword(), "");} }5.3 UserMapper.java
package com.lcy.demo.mapper;import com.lcy.demo.pojo.User;import java.util.List;public interface UserMapper {int deleteByPrimaryKey(Integer id);int insert(User record);User selectByPrimaryKey(Integer id);List<User> selectAll();int updateByPrimaryKey(User record);public User findByName(String name);public User findById(Integer id); }5.4 UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.lcy.demo.mapper.UserMapper"><resultMap id="BaseResultMap" type="com.lcy.demo.pojo.User"><id column="id" property="id" jdbcType="INTEGER"/><result column="user" property="user" jdbcType="VARCHAR"/><result column="password" property="password" jdbcType="VARCHAR"/></resultMap><delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">delete from userwhere id = #{id,jdbcType=INTEGER}</delete><insert id="insert" parameterType="com.lcy.demo.pojo.User">insert into user (id, user, password)values (#{id,jdbcType=INTEGER}, #{user,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR})</insert><update id="updateByPrimaryKey" parameterType="com.lcy.demo.pojo.User">update userset user = #{user,jdbcType=VARCHAR},password = #{password,jdbcType=VARCHAR}where id = #{id,jdbcType=INTEGER}</update><select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer">select id, user, passwordfrom userwhere id = #{id,jdbcType=INTEGER}</select><select id="selectAll" resultMap="BaseResultMap">select id, user, passwordfrom user</select><select id="findByName" resultMap="BaseResultMap">select id, user, passwordfrom user where user=#{value}</select><select id="findById" resultMap="BaseResultMap">select id, user, password,permsfrom user where id=#{value}</select> </mapper>5.5 UserService
package com.lcy.demo.Service;import com.lcy.demo.pojo.User;public interface UserService {public User findByName(String name);public User findById(Integer id); }5.6 UserServiceImpl
package com.lcy.demo.ServiceImpl;import com.lcy.demo.Service.UserService; import com.lcy.demo.mapper.UserMapper; import com.lcy.demo.pojo.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;@Service public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Overridepublic User findByName(String name) {return userMapper.findByName(name);}@Overridepublic User findById(Integer id) {return userMapper.findById(id);} }5.7 application.properties
server.port=8080 spring.mvc.view.prefix=/ spring.mvc.view.suffix=.html spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/shiro?useUnicode=true&characterEncoding=utf8 spring.datasource.username=root spring.datasource.password=111111spring.datasource.type=com.alibaba.druid.pool.DruidDataSource mybatis.type-aliases-package=com.lcy.demo.pojo# mybatis 配置 mybatis.mapper-locations=classpath:mapper/*.xml5.8 UserController
package com.lcy.demo.controller;import com.lcy.demo.Service.UserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping;@Controller public class UserController {@Autowiredprivate UserService userService;/*** 處理登錄邏輯** @param name* @param password* @param model* @return*/@RequestMapping("/login")public String login(String name, String password, Model model) {System.out.println("name" + name);/*** 使用shiro編寫認證操作*/ // 1、獲取subjectSubject subject = SecurityUtils.getSubject(); // 2、封裝用戶數據UsernamePasswordToken token = new UsernamePasswordToken(name, password); // 3、執行登錄的方法/*** 沒有出現異常:* 則登錄成功* 出現異常:* UnknownAccountException: 用戶名不存在* IncorrectCredentialsException: 密碼錯誤*/try {subject.login(token);return "redirect:/test";} catch (UnknownAccountException e) {model.addAttribute("msg", "用戶名不存在");return "login";} catch (IncorrectCredentialsException e) {model.addAttribute("msg", "密碼錯誤");return "login";}}@RequestMapping("/hh")public String tm(Model model) {model.addAttribute("name", "lcy ");return "tm";}}六、所需要的依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- shiro-spring --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.4.0</version></dependency><!-- thymeleaf模板 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId><version>2.1.9.RELEASE</version></dependency><!-- mybatis-spring-boot-starter --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.2</version></dependency><!-- mybatis 逆向生成工具 --><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.3.2</version><scope>compile</scope><optional>true</optional></dependency><!-- mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.38</version></dependency><!-- https://mvnrepository.com/artifact/com.alibaba/druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.12</version></dependency>總結
以上是生活随笔為你收集整理的shiro权限管理框架学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 错题集(求助中):爬虫碰到cookies
- 下一篇: 使用ntsd命令强制性杀掉进程[微软未开