1 . 添加依赖

<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.2.5</version>
</dependency>
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-ehcache</artifactId><version>1.2.5</version>
</dependency>

2 . 编写Shiro配置类

package com.xbz.web.system.config;import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.MemorySessionDAO;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;/*** shiro配置类* ApacheShiro核心通过Filter来实现权限控制和拦截 , 就好像SpringMVC通过DispachServlet来主控制请求分发一样 . * 既然是使用Filter , 即是通过URL规则来进行过滤和权限校验 , 所以我们需要定义一系列关于URL的规则和访问权限*/
@Configuration
public class ShiroConfiguration {/*** DefaultAdvisorAutoProxyCreator , Spring的一个bean , 由Advisor决定对哪些类的方法进行AOP代理 .*/@Bean@ConditionalOnMissingBeanpublic DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();defaultAAP.setProxyTargetClass(true);return defaultAAP;}/*** ShiroFilterFactoryBean : 为了生成ShiroFilter , 处理拦截资源文件问题 .* 它主要保持了三项数据 , securityManager , filters , filterChainDefinitionManager .* 注意 : 单独一个ShiroFilterFactoryBean配置是或报错的 , 因为在初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager** FilterChain定义说明* 1 . 一个URL可以配置多个Filter , 使用逗号分隔* 2 . 当设置多个过滤器时 , 全部验证通过 , 才视为通过* 3 . 部分过滤器可指定参数 , 如perms , roles**/@Beanpublic ShiroFilterFactoryBean shiroFilterFactoryBean() {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();shiroFilterFactoryBean.setSecurityManager(securityManager());shiroFilterFactoryBean.setLoginUrl("/login");//不设置默认找web工程根目录下的login.jsp页面shiroFilterFactoryBean.setSuccessUrl("/index");//登录成功之后要跳转的连接shiroFilterFactoryBean.setUnauthorizedUrl("/403");//未授权跳转页面/* //自定义拦截器 , 多个filter的设置 */
//        Map<String, Filter> filters = new LinkedHashMap<>();
//        LogoutFilter logoutFilter = new LogoutFilter();//限制同一帐号同时在线的个数。或单点登录等
//        logoutFilter.setRedirectUrl("/login");
//        filters.put("logout",null);
//        shiroFilterFactoryBean.setFilters(filters);Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();//filterChainDefinitionManager必须是LinkedHashMap因为它必须保证有序filterChainDefinitionMap.put("/css/**", "anon");//静态资源不要求权限 , 若有其他目录下文件(如js,img等)也依此设置filterChainDefinitionMap.put("/", "anon");filterChainDefinitionMap.put("/login", "anon");//配置不需要权限访问的部分urlfilterChainDefinitionMap.put("/logout", "logout");filterChainDefinitionMap.put("/user/**", "authc,roles[ROLE_USER]");//用户为ROLE_USER 角色可以访问 . 由用户角色控制用户行为 . filterChainDefinitionMap.put("/events/**", "authc,roles[ROLE_ADMIN]");//        filterChainDefinitionMap.put("/user/edit/**", "authc,perms[user:edit]");// 这里为了测试 , 固定写死的值 , 也可以从数据库或其他配置中读取 , 此处是用权限控制filterChainDefinitionMap.put("/**", "authc");//需要登录访问的资源 , 一般将/**放在最下边shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);return shiroFilterFactoryBean;}//region Cookie及Session// ==================== Cookie及Session管理 begin ====================private static final String COOKIE_NAME = "rememberMe";/** cookie对象管理 */public SimpleCookie rememberMeCookie(){//这个参数是cookie的名称,对应前端的checkbox的name = rememberMeSimpleCookie simpleCookie = new SimpleCookie(COOKIE_NAME);simpleCookie.setMaxAge(604800);//记住我cookie生效时间7天 ,单位秒return simpleCookie;}/** cookie管理对象 : 记住我功能 */public CookieRememberMeManager rememberMeManager(){CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();cookieRememberMeManager.setCookie(rememberMeCookie());cookieRememberMeManager.setCipherKey(Base64.decode("3AvVhmFLUs0KTA3Kprsdag=="));//rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)return cookieRememberMeManager;}@BeanSessionDAO sessionDAO() {return new MemorySessionDAO();}@Beanpublic SessionManager sessionManager() {DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();Collection<SessionListener> listeners = new ArrayList<>();listeners.add(new BDSessionListener());sessionManager.setSessionListeners(listeners);sessionManager.setSessionDAO(sessionDAO());return sessionManager;}// ==================== Cookie及Session管理 end ====================//endregion/*** SecurityManager : 核心安全事务管理器 , 权限管理*  这个类组合了登陆 , 登出 , 权限 , session的处理 . 是个比较重要的类 .*/@Bean(name = "securityManager")public DefaultWebSecurityManager securityManager() {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(shiroRealm());securityManager.setCacheManager(ehCacheManager());用户授权/认证信息Cache, 采用EhCache 缓存// 自定义session管理 使用redissecurityManager.setSessionManager(sessionManager());//注入记住我管理器;securityManager.setRememberMeManager(rememberMeManager());return securityManager;}/*** ShiroRealm , 这是个自定义的认证类 , 继承自AuthorizingRealm ,* 负责用户的认证和权限的处理 , 可以参考JdbcRealm的实现 .*/@Bean@DependsOn("lifecycleBeanPostProcessor")public ShiroRealm shiroRealm(CredentialsMatcher matcher) {ShiroRealm realm = new ShiroRealm();realm.setCredentialsMatcher(matcher);//密码校验实现return realm;}/*** EhCacheManager , 缓存管理* 用户登陆成功后 , 把用户信息和权限信息缓存起来 , 然后每次用户请求时 , 放入用户的session中 , 如果不设置这个bean , 每个请求都会查询一次数据库 .*/@Bean@DependsOn("lifecycleBeanPostProcessor")public EhCacheManager ehCacheManager() {EhCacheManager em = new EhCacheManager();em.setCacheManagerConfigFile("classpath:config/ehcache.xml");//配置文件路径return em;}/*** LifecycleBeanPostProcessor , 这是个DestructionAwareBeanPostProcessor的子类 ,* 负责org.apache.shiro.util.Initializable类型bean的生命周期的 , 初始化和销毁 .* 主要是AuthorizingRealm类的子类 , 以及EhCacheManager类 .*/@Bean(name = "lifecycleBeanPostProcessor")public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {return new LifecycleBeanPostProcessor();}/*** HashedCredentialsMatcher , 这个类是为了对密码进行编码的 ,* 防止密码在数据库里明码保存 , 当然在登陆认证的时候 ,* 这个类也负责对form里输入的密码进行编码* 处理认证匹配处理器:如果自定义需要实现继承HashedCredentialsMatcher*/@Bean(name = "hashedCredentialsMatcher")public HashedCredentialsMatcher hashedCredentialsMatcher() {HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();credentialsMatcher.setHashAlgorithmName("MD5");//指定加密方式方式,也可以在这里加入缓存,当用户超过五次登陆错误就锁定该用户禁止不断尝试登陆credentialsMatcher.setHashIterations(2);credentialsMatcher.setStoredCredentialsHexEncoded(true);return credentialsMatcher;}/*** AuthorizationAttributeSourceAdvisor , shiro里实现的Advisor类 ,* 内部使用AopAllianceAnnotationsAuthorizingMethodInterceptor来拦截用以下注解的方法 .*/@Beanpublic AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();advisor.setSecurityManager(securityManager());return advisor;}//thymeleaf模板引擎和shiro整合时使用@Beanpublic ShiroDialect shiroDialect() {return new ShiroDialect();}
}

3 . 自定义Realm验证类

package com.yiyun.web.system.config;import com.yiyun.dao.master.UserDao;
import com.yiyun.domain.UserDO;
import com.yiyun.web.common.utils.ShiroUtils;
import com.yiyun.web.system.service.MenuService;
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.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;import java.util.*;/***  获取用户的角色和权限信息*/
public class ShiroRealm extends AuthorizingRealm {// 一般这里都写的是servic@Autowiredprivate UserDao userMapper;@Autowiredprivate MenuService menuService;/***  登录认证 一般情况下 , 登录成功之后就给当前用户进行权限赋予了*  根据用户的权限信息做授权判断,这一步是以doGetAuthenticationInfo为基础的,只有在有用户信息后才能根据用户的角色和授权信息做判断是否给用户授权,因此这里的Roles和Permissions是用户的两个重点判断依据* @param authenticationToken* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;UserDo user = userMapper.findByName(token.getUsername());//查出是否有此用户if(user != null){// 若存在,将此用户存放到登录认证info中,无需自己做密码对比,Shiro会为我们进行密码对比校验List<URole> rlist = uRoleDao.findRoleByUid(user.getId());//获取用户角色List<UPermission> plist = uPermissionDao.findPermissionByUid(user.getId());//获取用户权限List<String> roleStrlist=new ArrayList<String>();用户的角色集合List<String> perminsStrlist=new ArrayList<String>();//用户的权限集合for (URole role : rlist) {roleStrlist.add(role.getName());}for (UPermission uPermission : plist) {perminsStrlist.add(uPermission.getName());}user.setRoleStrlist(roleStrlist);user.setPerminsStrlist(perminsStrlist);Session session = SecurityUtils.getSubject().getSession();session.setAttribute("user", user);//成功则放入session// 若存在,将此用户存放到登录认证info中,无需自己做密码对比,Shiro会为我们进行密码对比校验return new SimpleAuthenticationInfo(user, user.getPassword(), getName());}return null;}/*** 权限认证* 获取用户的权限信息,这是为下一步的授权做判断,获取当前用户的角色和这些角色所拥有的权限信息* @param principalCollection* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {//获取当前登录输入的用户名,等价于(String) principalCollection.fromRealm(getName()).iterator().next();
//        String loginName = (String) super.getAvailablePrincipal(principalCollection);UserDo user = (UserDo) principalCollection.getPrimaryPrincipal();
//        //到数据库查是否有此对象
//        User user = null;// 实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法
//        user = userMapper.findByName(loginName);if (user != null) {//权限信息对象info,用来存放查出的用户的所有的角色(role)及权限(permission)SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//用户的角色集合info.addRoles(user.getRoleStrlist());//用户的权限集合info.addStringPermissions(user.getPerminsStrlist());return info;}// 返回null的话,就会导致任何用户访问被拦截的请求时,都会自动跳转到unauthorizedUrl指定的地址return null;}
}

4 . 最后看一下ehcache的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"updateCheck="false"><diskStore path="java.io.tmpdir/Tmp_EhCache" /><!--name:缓存名称。maxElementsInMemory:缓存最大数目maxElementsOnDisk:硬盘最大缓存个数。eternal:对象是否永久有效,一但设置了,timeout将不起作用。overflowToDisk:是否保存到磁盘,当系统当机时timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。clearOnFlush:内存数量最大时是否清除。memoryStoreEvictionPolicy:Ehcache的三种清空策略;FIFO,first in first out,这个是大家最熟的,先进先出。LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。--><defaultCache eternal="false" maxElementsInMemory="1000"overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0"timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU" /><!-- 登录记录缓存锁定10分钟 --><cache name="passwordRetryCache"maxEntriesLocalHeap="2000"eternal="false"timeToIdleSeconds="3600"timeToLiveSeconds="0"overflowToDisk="false"statistics="true"></cache>
</ehcache>

SpringBoot集成Shiro进行权限控制和管理相关推荐

  1. SpringBoot整合Shiro实现权限控制,验证码

    本文介绍 SpringBoot 整合 shiro,相对于 Spring Security 而言,shiro 更加简单,没有那么复杂. 目前我的需求是一个博客系统,有用户和管理员两种角色.一个用户可能有 ...

  2. springboot整合shiro实现权限控制

    博主简介:原互联网大厂tencent员工,网安巨头Venustech员工,阿里云开发社区专家博主,微信公众号java基础笔记优质创作者,csdn优质创作博主,创业者,知识共享者,欢迎关注,点赞,收藏. ...

  3. 全程配图超清晰的Springboot权限控制后台管理项目实战第二期(Springboot+shiro+mybatis+redis)

    全程配图超清晰的Springboot权限控制后台管理项目实战第二期(Springboot+shiro+mybatis+redis) 众所周知,作为一个后端新手学习者,通过项目来学习,增长项目经验,是一 ...

  4. 《SpringBoot与Shiro整合-权限管理实战---从构建到模拟数据库登入》

    <SpringBoot与Shiro整合-权限管理实战> ---- 从构建到模拟数据库登入 ---- 点击下载源码 ---- 或者查看? 文章目录 <SpringBoot与Shiro整 ...

  5. SpringMvc 集成 shiro 实现权限角色管理-maven

    2019独角兽企业重金招聘Python工程师标准>>> SpringMvc 集成 shiro 实现权限角色管理 1.项目清单展示 2.项目源码解析  1)spring-context ...

  6. SpringBoot整合SpringSecurity实现权限控制(五):用户管理

    系列文章目录 <SpringBoot整合SpringSecurity实现权限控制(一):实现原理> <SpringBoot整合SpringSecurity实现权限控制(二):权限数据 ...

  7. SpringBoot集成Shiro安全框架

    SpringBoot集成Shiro安全框架 1.shiro的定义 2.SpringBoot集成shiro的步骤 3.完成的效果 1.shiro的定义 1.shiro的作用 认证.授权.加密.会话管理. ...

  8. springboot集成shiro实现用户登录认证

    Apache Shiro 是一个功能强大且易于使用的Java安全框架,可执行身份验证.授权.加密和会话管理.使用Shiro易于理解的API,您可以快速轻松地保护任何应用程序-从最小的移动应用程序到最大 ...

  9. SpringBoot整合SpringSecurity+Redis权限控制

    SpringBoot整合SpringSecurity+Redis权限控制 1.认识SpringSecurity 2.效果截图 2.1.登录接口 2.2.注册接口 2.3.管理员权限接口 2.4.普通用 ...

最新文章

  1. onmouseout事件与onchange事件分析
  2. c#.net 获取时间日期年月日时分秒生成自动文件名格式
  3. 旷视研究院博士图鉴|Be that challenger
  4. 黄聪:CodeSmith和PowerDesigner的使用安装和数据库创建(原创系列教程)
  5. 视觉错觉模型_极具视觉爆发力的影院设计
  6. MaxCompute平台非标准日期和气象数据处理方法--以电力AI赛为例
  7. Magrittr包:简化你的R代码
  8. Flink Forward Asia 2019 - 总结和展望(附PPT下载链接)
  9. 【转(比较全面)】CSS3弹性盒模型之Flexbox是布局模块box-sizing box-orient box-direction box-ordinal-group
  10. FI财务会计全局设置
  11. 在C#中obsolete表示什么?
  12. HDTV 之-HDMI HPD
  13. python七段数码管显示学号_python小实例——七段数码管绘制
  14. 定时限过电流保护整定计算
  15. python飞机大战联网版_Python实现飞机大战(搞怪)游戏!这是你没见过的全新版本!...
  16. element ui table实现考勤排班表
  17. cad记忆口诀_42条简单易记的CAD口诀,一天精通入门,七天上手绘图!
  18. 系统的认识大数据人工智能数据分析中的数据
  19. MySQL表级锁之表锁
  20. android端蓝牙控制单片机,android 蓝牙控制继电器——单片机控制端

热门文章

  1. C#基础视频教程4.3 如何编写简单的计算器
  2. android WebView总 结
  3. iOS开发中对NSArray或者NSMutableArray中的内容排序
  4. Button按钮多行显示的实现方法
  5. 前展(规划)后延(架设):编码开发程序员的出路之一
  6. [Vue.js]实战 -- 电商项目(一)
  7. 添加standardjs和eslint配置检测代码规范步骤
  8. 关于JavaScript中cookie的用法例子
  9. Vue「六」前端路由、vue-router
  10. oracle安全性规则,[ORACLE ]安全性