其实关于Shiro的一些学习笔记很早就该写了,因为懒癌和拖延症晚期一直没有落实,直到今天公司的一个项目碰到了在集群环境的单点登录频繁掉线的问题,为了解决这个问题,Shiro相关的文档和教程没少翻。最后问题解决了,但我觉得我也是时候来做一波Shiro学习笔记了。

先给自己定个博客计划吧,不然很可能又要难产了。本次预计的篇幅量在三篇,第一篇先记录一下Shiro的基本使用,第二篇写一下基于Shiro实现的集群环境中的Session共享,第三篇深入Shiro框架看一下核心源码,会使用只是皮毛,了解原理才算真正学会框架。嗯,就先这么定吧。


核心概念

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

上面这段话来自百度百科,是不是非常官方,好像说的很明白但是又好像什么都没说的样子,到底是个啥呀。想要快速理解并使用Shiro先要从最重要的三大概念入手。

  1. Subject:大白话来讲就是用户(当然并不一定是用户,也可以指和当前应用交互的任何对象),我们在进行授权鉴权的所有操作都是围绕Subject(用户)展开的,在当前应用的任何地方都可以通过SecurityUtils的静态方法getSubject()轻松的拿到当前认证(登录)的用户。
  2. SecurityManager:安全管理器,Shiro中最核心的组件,它管理着当前应用中所有的安全操作,包括Subject(用户),我们围绕Subject展开的所有操作都需要与SecurityManager进行交互。可以理解为SpringMVC中的前端控制器。
  3. Realms:字面意思为领域,Shiro在进行权限操作时,需要从Realms中获取安全数据,也就是用户以及用户的角色和权限。配置Shiro,我们至少需要配置一个Realms,用于用户的认证和授权。通常我们的角色及权限信息都是存放在数据库中,所以Realms也可以算是一个权限相关的Dao层,SecurityManager在进行鉴权时会从Realms中获取权限信息。

这三个基本的概念简答理解后就可以开始配置和使用Shiro了,其实Shiro最基本的使用非常简单,加入依赖后只需要配置两个Bean,再继承一个抽象类实现两个方法即可。


基本使用

引入一个依赖

新建一个基于Springboot的Web项目,引入Shiro依赖。

<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-web -->
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.4.0</version>
</dependency>

配置两个Bean

新建一个Shiro配置类,配置Shiro最为核心的安全管理器SecurityManager。

@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();shiroFilterFactoryBean.setSecurityManager(securityManager);// 登录页面,无权限时跳转的路径shiroFilterFactoryBean.setLoginUrl("/login");// 配置拦截规则Map<String, String> filterMap = new HashMap<>();// 首页配置放行filterMap.put("/", "anon");// 登录页面和登录请求路径需要放行filterMap.put("/login", "anon");filterMap.put("/do_login", "anon");// 其他未配置的所有路径都需要通过验证,否则跳转到登录页filterMap.put("/**", "authc");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);return shiroFilterFactoryBean;
}

上面Filter的配置顺序不能随便打乱,过滤器是按照我们配置的顺序来执行的。范围大的过滤器要放在后面,/**这条如果放在前面,那么一来就匹配上了,就不会继续再往后走了。这里的对上面用到的两个过滤器做一下简单说明,篇幅控制其他过滤器请参阅相关文档:

* authc:配置的url都必须认证通过才可以访问,它是Shiro内置的一个过滤器
* 对应的实现类 @see org.apache.shiro.web.filter.authc.FormAuthenticationFilter* anon:也是Shiro内置的,它对应的过滤器里面是空的,什么都没做,可以理解为不拦截
* 对应的实现类 @see org.apache.shiro.web.filter.authc.AnonymousFilter

实现两个方法

在上一步的安全管理器配置中,我们通过形参注入了一个UserAuthorizingRealm对象,这个就是认证和授权相关的流程,需要我们自己实现。继承AuthorizingRealm之后,我们需要实现两个抽象方法,一个是认证,一个是授权,这两个方法长得很像,别弄混淆了。

doGetAuthenticationInfo():认证。相当于登录,只有通过登录了,才能进行后面授权的操作。一些只需要登录权限的操作,在登录成功后就可以访问了,比如上一步中配置的authc过滤器就是只需要登录权限的。

doGetAuthorizationInfo():授权。认证过后,仅仅拥有登录权限,更多细粒度的权限控制,比如菜单权限,按钮权限,甚至方法调用权限等,都可以通过授权轻松实现。在这个方法里,我们可以拿到当前登录的用户,再根据实际业务赋予用户部分或全部权限,当然这里也可以赋予用户某些角色,后面也可以根据角色鉴权。下方的演示代码仅添加了权限,赋予角色可以调用addRoles()或者setRoles()方法,传入角色集合。

public class UserAuthorizingRealm extends AuthorizingRealm {@Autowiredprivate LoginService loginService;/*** 授权验证,获取授权信息*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {User user = (User) principalCollection.getPrimaryPrincipal();List<String> perms;// 系统管理员拥有最高权限if (User.SUPER_ADMIN == user.getId()) {perms = loginService.getAllPerms();} else {perms = loginService.getUserPerms(user.getId());}// 权限Set集合Set<String> permsSet = new HashSet<>();for (String perm : perms) {permsSet.addAll(Arrays.asList(perm.trim().split(",")));}// 返回权限SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();info.setStringPermissions(permsSet);return info;}/*** 登录验证,获取身份信息*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;// 获取用户User user = loginService.getUserByUsername(token.getUsername());if (user == null) {throw new UnknownAccountException("账号或密码不正确");}// 判断用户是否被锁定if (user.getStatus() == null || user.getStatus() == 1) {throw new LockedAccountException("账号已被锁定,请联系管理员");}// 验证密码if (!user.getPassword().equals(new String(token.getPassword()))) {throw new UnknownAccountException("账号或密码不正确");}user.setSessionId(SecurityUtils.getSubject().getSession().getId().toString());// 设置最后登录时间user.setLastLoginTime(new Date());// 此处可以持久化用户的登录信息,这里仅做演示没有连接数据库return new SimpleAuthenticationInfo(user, user.getPassword(), getName());}
}

这样配置完成以后,就可以基于URL做粗粒度的权限控制了,我们可以通过不同的过滤器为URL配置不同的权限。

Shiro提供了很多内置的过滤器,我们最常用的就是第一个和第二个。如果对其效果不满意,我们还可以自定义过滤器实现权限控制。
文档地址:http://shiro.apache.org/web.html#default-filters


细粒度权限控制

如果需要更细致的权限控制,请继续往下添加配置,可以做到方法级别的权限控制。其实在SpringMVC中URL也能做到方法级别控制,但是使用URL来控制方法级别的权限配置起来简直反人类,通常URL权限控制通常都是泛解析,做通用的权限配置,比如后台管理的/admin/**这种需要登录权限的。在实际开发中注解式的权限控制用的最多。

AdvisorAutoProxyCreator

注解式的权限控制需要配置两个Bean,第一个是AdvisorAutoProxyCreator,代理生成器,需要借助SpringAOP来扫描@RequiresRoles和@RequiresPermissions等注解,生成代理类实现功能增强,从而实现权限控制。需要配合AuthorizationAttributeSourceAdvisor一起使用,否则权限注解无效。

@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();autoProxyCreator.setProxyTargetClass(true);return autoProxyCreator;
}

AuthorizationAttributeSourceAdvisor

上面配置的DefaultAdvisorAutoProxyCreator相当于一个切面,下面这个类就相当于切点了,两个一起才能实现注解权限控制。

@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();advisor.setSecurityManager(securityManager);return advisor;
}

配置完上面两个Bean之后我们就可以使用注解来控制权限了,Shiro中的权限注解有很多,我们最常用的其实就两个,@RequiresRoles和@RequiresPermissions,前者是角色验证,后者是权限验证。他们都可以传入两个参数,value是必须的,可以传入一个字符数组,表示一个或多个角色(权限),另一个参数logical有两个值可选,AND和OR,默认为AND,表示这组角色(权限)是必须都有还是仅需要一个就能访问。

举个栗子:

@RequestMapping("getLoginUserInfo")
@RequiresPermissions(value = {"user:list", "user:info"}, logical = Logical.OR)
public JsonResult getLoginUserInfo() {Subject subject = SecurityUtils.getSubject();User user = (User) subject.getPrincipal();return JsonResult.ok(user);
}

以上代码表示getLoginUserInfo()方法需要当前登录用户拥有user:list或者user:list权限才能访问。

最后放上项目代码,其实代码是很早之前的,今天才做的笔记而已。

Gitee:https://gitee.com/guitu18/ShiroDemo

GitHub:https://github.com/guitu18/ShiroDemo


本篇结束,Shiro的使用还是非常简单的。下一篇,准备记录一下基于Springboot和Shiro使用Redis实现集群环境的Session共享,以实现单点登录。


原作者:Guitu
原文链接:Shiro权限管理框架(一):Shiro的基本使用
原出处:Guitu个人博客

shiro 单点登录_Shiro权限管理框架(一):Shiro的基本使用相关推荐

  1. 「单点登录与权限管理」系列概述

    首先,感谢几位朋友在朋友圈转发我的文章,小声的告诉你们,是我主动让他们帮忙转发的:)在朋友们的分享下,凌晨推送的一篇文章,阅读人数达到了280多,很满足,我会坚持写下去,分享工作.学习.生活中的所思所 ...

  2. 单点登录与权限管理本质:权限管理介绍

    前面几篇文章介绍了单点登录的本质,包括cookie.session.重定向的基本概念,单点登录的基本交互流程,cookie的重要性和安全问题.单点登录能够确保:必须通过身份验证后,才能访问网站,且访问 ...

  3. 单点登录与权限管理本质:session和cookie介绍

    本篇开始写「单点登录与权限管理」系列的第一部分:单点登录与权限管理本质,这部分主要介绍相关的知识概念.抽象的处理过程.常见的实现框架.通过这部分的介绍,能够对单点登录与权限管理有整体上的了解,对其相关 ...

  4. 单点登录与权限管理本质:cookie安全问题

    继续介绍「单点登录与权限管理」系列的第一部分:单点登录与权限管理本质,前一篇文章介绍了单点登录概念,以CAS协议的基本流程为例讲解了系统间的交互过程,过程中,cookie的设置和传输涉及的比较多,如何 ...

  5. 4a安全管控 java cas_单点登录与权限管理本质:单点登录介绍

    继续介绍「单点登录与权限管理」系列的第一部分:单点登录与权限管理本质,前两篇介绍了session与cookie 和 HTTP重定向 ,有了他们,浏览器就可以在多个系统间自动交互,实现自动登录. 本篇介 ...

  6. springBoot整合spring security+JWT实现单点登录与权限管理前后端分离

    在前一篇文章当中,我们介绍了springBoot整合spring security单体应用版,在这篇文章当中,我将介绍springBoot整合spring secury+JWT实现单点登录与权限管理. ...

  7. springBoot整合spring security+JWT实现单点登录与权限管理前后端分离--筑基中期

    写在前面 在前一篇文章当中,我们介绍了springBoot整合spring security单体应用版,在这篇文章当中,我将介绍springBoot整合spring secury+JWT实现单点登录与 ...

  8. 单点登录与权限管理本质:单点登录介绍

    继续介绍「单点登录与权限管理」系列的第一部分:单点登录与权限管理本质,前两篇介绍了session与cookie 和 HTTP重定向 ,有了他们,浏览器就可以在多个系统间自动交互,实现自动登录. 该系列 ...

  9. shiro 同时实现url和按钮的拦截_Shiro权限管理框架(一):Shiro的基本使用

    其实关于Shiro的一些学习笔记很早就该写了,因为懒癌和拖延症晚期一直没有落实,直到今天公司的一个项目碰到了在集群环境的单点登录频繁掉线的问题,为了解决这个问题,Shiro相关的文档和教程没少翻.最后 ...

最新文章

  1. 【Android 启动过程】Activity 启动源码分析 ( Activity -> AMS、主线程阶段 )
  2. Python 技术篇-index()字符串倒叙匹配获取索引,字符串切片反向输出,逆向输出字符串
  3. linux使关机命令失效,解决Linux系统在设置alias命令重启后失效的问题
  4. mysql可以存储标点么_MySQL查询(进阶)(每个标点都是重点)
  5. C++学习之路 | PTA乙级—— 1007 素数对猜想 (20分)(精简)
  6. Metasploit介绍
  7. Android音频开发(2):如何采集一帧音频
  8. 计算机网络中数据包的分布,计算机网络习题.doc
  9. java flv 转swf_swf转flv格式转换器 使用ffmpeg进行视频文件转换成FLV整理
  10. Go程序设计语言 第1章 入门
  11. 第二个项目---EMOS企业在线办公小程序
  12. sap销售发货的流程_SAP标准业务流程-销售订单处理
  13. 什么是zigbee?
  14. 国产旗舰手机定价近六千,却连iPhone12都打不过,用户选谁很明确
  15. Cadence 应用注意事项--转载
  16. java基于quasar实现协程池
  17. 笔记—集成学习—Boosting
  18. CVE-2014-0160-心脏滴血漏洞
  19. KEIL MDK RTX 实时操作系统
  20. RHCS基本理論(台湾人写的不错的文章)

热门文章

  1. 剑指offer面试题58 - I. 翻转单词顺序(双指针)
  2. GRPC编译安装及测试
  3. Qt之HTTP——发送HTTP请求
  4. 推荐一个站点:里面有很多不错的长文
  5. MySQL的主动优化和被动优化_MySQL“被动”性能优化汇总
  6. CodeChef June Challenge 2017
  7. sql 2008 清空数据库日志
  8. Bailian4119 复杂的整数划分问题【DP】
  9. Bailian2933 停车场收费【水题】
  10. UVA10450 POJ1953 World Cup Noise【斐波那契数列】