shiro权限管理框架学习
一、權(quán)限框架簡(jiǎn)介
基本上涉及到用戶參與的系統(tǒng)都要進(jìn)行權(quán)限管理,權(quán)限管理屬于系統(tǒng)安全的范疇,權(quán)限管理實(shí)現(xiàn)對(duì)用戶訪問系統(tǒng)的控制,按照安全規(guī)則或者安全策略控制用戶可以訪問而且只能訪問自己被授權(quán)的資源。權(quán)限管理包括用戶身份認(rèn)證和授權(quán)兩部分,簡(jiǎn)稱認(rèn)證授權(quán)。對(duì)于需要訪問控制的資源用戶首先經(jīng)過身份認(rèn)證,認(rèn)證通過后用戶具有該資源的訪問權(quán)限方可訪問。
二、shiro介紹
Shiro是apache旗下一個(gè)開源框架,它將軟件系統(tǒng)的安全認(rèn)證相關(guān)的功能抽取出來,實(shí)現(xiàn)用戶身份認(rèn)證,權(quán)限授權(quán)、加密、會(huì)話管理等功能,組成了一個(gè)通用的安全認(rèn)證框架。
三、shiro架構(gòu)
四、shiro架構(gòu)中核心組件
4.1 Subject
Subject即主體,外部應(yīng)用與subject進(jìn)行交互,subject記錄了當(dāng)前操作用戶,將用戶的概念理解為當(dāng)前操作的主體,可能是一個(gè)通過瀏覽器請(qǐng)求的用戶,也可能是一個(gè)運(yùn)行的程序。Subject在shiro中是一個(gè)接口,接口中定義了很多認(rèn)證授相關(guān)的方法,外部程序通過subject進(jìn)行認(rèn)證授,而subject是通過SecurityManager安全管理器進(jìn)行認(rèn)證授權(quán)
4.2 SecurityManager
SecurityManager即安全管理器,對(duì)全部的subject進(jìn)行安全管理,它是shiro的核心,負(fù)責(zé)對(duì)所有的subject進(jìn)行安全管理。通過SecurityManager可以完成subject的認(rèn)證、授權(quán)等,實(shí)質(zhì)上SecurityManager是通過Authenticator進(jìn)行認(rèn)證,通過Authorizer進(jìn)行授權(quán),通過SessionManager進(jìn)行會(huì)話管理等。
SecurityManager是一個(gè)接口,繼承了Authenticator, Authorizer, SessionManager這三個(gè)接口。
4.3 Authenticator
Authenticator即認(rèn)證器,對(duì)用戶身份進(jìn)行認(rèn)證,Authenticator是一個(gè)接口,shiro提供ModularRealmAuthenticator實(shí)現(xiàn)類,通過ModularRealmAuthenticator基本上可以滿足大多數(shù)需求,也可以自定義認(rèn)證器。
4.4 Authorizer
Authorizer即授權(quán)器,用戶通過認(rèn)證器認(rèn)證通過,在訪問功能時(shí)需要通過授權(quán)器判斷用戶是否有此功能的操作權(quán)限。
4.5 realm
Realm即領(lǐng)域,相當(dāng)于datasource數(shù)據(jù)源,securityManager進(jìn)行安全認(rèn)證需要通過Realm獲取用戶權(quán)限數(shù)據(jù),比如:如果用戶身份數(shù)據(jù)在數(shù)據(jù)庫(kù)那么realm就需要從數(shù)據(jù)庫(kù)獲取用戶身份信息。
注意:不要把realm理解成只是從數(shù)據(jù)源取數(shù)據(jù),在realm中還有認(rèn)證授權(quán)校驗(yàn)的相關(guān)的代碼。
4.6 sessionManager
sessionManager即會(huì)話管理,shiro框架定義了一套會(huì)話管理,它不依賴web容器的session,所以shiro可以使用在非web應(yīng)用上,也可以將分布式應(yīng)用的會(huì)話集中在一點(diǎn)管理,此特性可使它實(shí)現(xiàn)單點(diǎn)登錄。
4.7 SessionDAO
SessionDAO即會(huì)話dao,是對(duì)session會(huì)話操作的一套接口,比如要將session存儲(chǔ)到數(shù)據(jù)庫(kù),可以通過jdbc將會(huì)話存儲(chǔ)到數(shù)據(jù)庫(kù)。
4.8 CacheManager
CacheManager即緩存管理,將用戶權(quán)限數(shù)據(jù)存儲(chǔ)在緩存,這樣可以提高性能。
4.9 Cryptography
Cryptography即密碼管理,shiro提供了一套加密/解密的組件,方便開發(fā)。比如提供常用的散列、加/解密等功能。
五、springboot+shiro+mybatis實(shí)現(xiàn)動(dòng)態(tài)權(quán)限管理
5.1 創(chuàng)建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 {//創(chuàng)建一個(gè)ShiroFilterFactoryBean@Beanpublic ShiroFilterFactoryBean getshiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();//設(shè)置安全管理器shiroFilterFactoryBean.setSecurityManager(securityManager);//shiro的內(nèi)置過濾器/*** shiro內(nèi)置過濾器,可以實(shí)現(xiàn)權(quán)限相關(guān)的攔截器* 常用的過濾器:* anon:無需認(rèn)證(登錄)可以訪問* authc:必須認(rèn)證才可以訪問* User:如果使用rememberMe的功能可以直接訪問* perms: 該資源必須得到資源權(quán)限才可以訪問* role:該資源必須得到角色權(quán)限才可以直接訪問*///進(jìn)行攔截Map<String, String> filtermap = new LinkedHashMap<String, String>();// filtermap.put("/add", "authc"); // filtermap.put("/update", "authc");// 無需驗(yàn)證filtermap.put("/test", "anon");// 放行l(wèi)ogin.html頁(yè)面filtermap.put("/login", "anon");//授權(quán)攔截器 當(dāng)授權(quán)被攔截后 shiro會(huì)自動(dòng)跳到未授權(quán)的頁(yè)面filtermap.put("/add", "perms[user:add]");filtermap.put("/update", "perms[user:update]");// 使用通配的方式進(jìn)行攔截(同一目錄下的靜態(tài)資源)filtermap.put("/*", "authc");shiroFilterFactoryBean.setLoginUrl("/toLogin"); // 設(shè)置未授權(quán)提示的頁(yè)面shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth");shiroFilterFactoryBean.setFilterChainDefinitionMap(filtermap);return shiroFilterFactoryBean;}//創(chuàng)建一個(gè)DefaultWebSecuritManager@Bean(name = "securityManager")public DefaultWebSecurityManager getdefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();//關(guān)聯(lián)RealmsecurityManager.setRealm(userRealm);return securityManager;}//創(chuàng)建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的兩大核心 認(rèn)證和授權(quán)*/ public class UserRealm extends AuthorizingRealm {/*** 執(zhí)行授權(quán)邏輯** @param principalCollection* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("執(zhí)行授權(quán)邏輯");SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();// 添加資源的授權(quán)字符串 // info.addStringPermission("user:add");// 到數(shù)據(jù)庫(kù)查詢當(dāng)前登錄用戶的授權(quán)字符串 // 獲取當(dāng)前的用戶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;/*** 執(zhí)行認(rèn)證邏輯** @param authenticationToken* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {System.out.println("執(zhí)行認(rèn)證邏輯");// 編寫shiro的認(rèn)證邏輯 判斷用戶名和密碼UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;User user = userService.findByName(token.getUsername());if (user == null) {//用戶名不存在return null;//shiro底層會(huì)拋出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編寫認(rèn)證操作*/ // 1、獲取subjectSubject subject = SecurityUtils.getSubject(); // 2、封裝用戶數(shù)據(jù)UsernamePasswordToken token = new UsernamePasswordToken(name, password); // 3、執(zhí)行登錄的方法/*** 沒有出現(xiàn)異常:* 則登錄成功* 出現(xiàn)異常:* UnknownAccountException: 用戶名不存在* IncorrectCredentialsException: 密碼錯(cuò)誤*/try {subject.login(token);return "redirect:/test";} catch (UnknownAccountException e) {model.addAttribute("msg", "用戶名不存在");return "login";} catch (IncorrectCredentialsException e) {model.addAttribute("msg", "密碼錯(cuò)誤");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>總結(jié)
以上是生活随笔為你收集整理的shiro权限管理框架学习的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 错题集(求助中):爬虫碰到cookies
- 下一篇: 使用ntsd命令强制性杀掉进程[微软未开