SpringBoot 项目 Shiro 的实现
SpringBoot 整合 Shiro
- 一、Shiro 的简介
- 二、Shiro 的实现。
- 独立应用程序
- 2.1、SSM 框架配置文件的方式 集成 Apache Shiro 。
- 2.2、Spring Boot 集成 Apache Shiro 。
- 三、Shiro 的方法总结。
- 3.1、Shiro 支持三种方式的授权。
- 3.2、@RequiresRoles 和 @RequiresPermissions 注解不生效。
- 3.3、Shiro 的注解。
- 3.4、unauthorizedUrl 无效。
- 3.5、AJAX 请求,提示无角色无权限。
2019-04-30, 明天是五一劳动节,准备在4月结束前把 Token 令牌登录(SpringBoot 整合 JWT )的项目接口与将文件管理系统的接口对接,发现学长给的这个用户认证登录的接口有些问题(后续再说),没能顺利的进行。
- 在学习 SSM 框架的时候,有接触到 Shiro ,其中的登录是通过 Token 完成的。这样我便开始 SpringBoot 整合 Shiro。
一、Shiro 的简介
- Shiro 的官网 :http://shiro.apache.org/
- 将Apache Shiro集成到基于Spring的应用程序中
Shiro 完整架构图
Shiro 是 Apache 下的一个开源项目(Apache Shiro),是一个易用与 Java 项目的安全框架,提供了 认证、授权、加密、会话管理,与 Spring Security 一样都是做了一个权限的安全框架。
Shiro 核心的三大组件
Shiro 的三大核心组件:
1、Subject 当前用户。
2、SecurityManage 管理所有的 Subject 。
3、Reamls 权限信息的验证 。
除了三大组件,还要认识的内容:
* authenticator:认证器,主体进行认证最终通过authenticator进行的。
* authorizer:授权器,主体进行授权最终通过authorizer进行的。
* sessionManager:web应用中一般是用web容器对session进行管理,shiro也提供一套 - session管理的方式。
* SessionDao: 通过SessionDao管理session数据,针对个性化的session数据存储需要使用sessionDao。
* cache Manager:缓存管理器,主要对session和授权数据进行缓存,比如将授权数据通过cacheManager进行缓存管理,和ehcache整合对缓存数据进行管理。
* realm:域,领域,相当于数据源,通过realm存取认证、授权相关数据。
* cryptography:密码管理,提供了一套加密/解密的组件,方便开发。比如提供常用的散列、加/解密等功能。比如 md5散列算法。
Shiro 的实现要点:
1、实现 Reamls 的 Authentication(验证用户的身份) 与 Authorization(用户授权访问控制)。
2、Shiro 是通过 Filter(过滤器)来实现的,就好比 SpringMVC 使用 DispatchServlet 来做控制,就是多个过滤器按照顺序执行。Shiro 是通过 URL 匹配规则来进行过滤和权限校验的,所以我们需要定义一系列的 URL 规则和访问权限。
Shiro 默认的拦截器 | 拦截器描述 | 用例 | 过滤器的类 org.apache.shiro.web.filter |
---|---|---|---|
anon | 可匿名访问 | 注册等可以匿名访问。/admin/register/**=anon | .authc.AnonymousFilter |
authc | 认证成功后才能使用(Authorization 执行成功) | 设置需要认证权限的界面。/user/**=authc | .authc.FormAuthenticationFilter |
logout | 注销登录的时候,任何 Session 都失效,任何身份都将失效 | 用户退出。/logout=logout | .authc.LogoutFilter |
authcBasic | 表示需通过 HttpBasic验证 | /user/**=authBasic | .authc.BasicHttpAuthenticationFilter |
perms | 权限过滤器 | /admins/**=perms[user:add:*];/admins/user/**=perms[“user:add:*,user:modify:*”] | .authz.PermissionsAuthorizationFilter |
port | 端口过滤器,可以设置是否是指定端口如果不是跳转到登录页面 | /admins/**=port[8081] | .authz.PortFilter |
rest | http方法过滤器 | 可以指定如post不能进行访问等,/admins/user/**=rest[user:method],其中method 为 post、get等 | .authz.HttpMethodPermissionFilter |
roles | 角色过滤器,判断当前用户是否指定角色。当有多个参数时,每个参数通过才算通过,相当于 hasAllRoles() 方法 | /admins/**=roles[“admin,guest”] | .authz.RolesAuthorizationFilter |
ssl | 请求需要通过ssl,如果不是跳转登录页 | 暂无 | .authz.SslFilter |
user | 如果访问一个已知用户,比如记住我功能,走这个过滤器 | 暂无 | .authc.UserFilter |
noSessionCreation | 阻止在请求期间创建新的会话。以保证无状态的体验 | 暂无 | .session.NoSessionCreationFilter |
3、Shiro 通过提供的会话管理可以获取 Session 中的信息,同样可以使用 CacheManage 来管理。
4、Shiro 的认证流程:
(1)、在登录页面输入账号密码,传递给 Controller,在 Controller 中通过 Security.getSubject() 获取当前的 Subject 。
(2)、通过 Subject 的 isAuthenticated() ,验证当前用户是否已经被认证。
(3)、如果没有被认证,则开始认证。
(4)、将从前台传来的账号密码封装到一个 UsernamePasswordToken 对象中。
(5)、调用当前 Subject 的 login() 方法。这会把 token 作为参数传递到自定义的 Realm 的 doGetAuthenticationInfo()方法中。
(6)、在 doGetAuthenticationInfo() 方法中,首先将 AuthenticationToken 转换为 UsernamePasswordToken 对象,然后调用 Service 层,根据 UsernamePasswordToken 中的用户名到数据库中去查询密码。
(7)、由 Shiro 完成密码的比对,密码的比对是通过 AuthenticatingRealm 的 credentialsMatcher 属性来进行比对的。
5、Shiro 的授权流程。
(1)、构造 SecurityManager 环境后,对 subject 进行授权,调用方法 isPermitted(”permission串”)
(2)、SecurityManager 执行授权,通过 ModularRealmAuthorizer 执行授权
(3)、ModularRealmAuthorizer 执行 realm(自定义的CustomRealm)从数据库查询权限数据
调用realm的授权方法:doGetAuthorizationInfo()
(4)、realm 从数据库查询权限数据,返回ModularRealmAuthorizer
(5)、ModularRealmAuthorizer 调用 PermissionResolver 进行权限串比对
(6)、如果比对后,isPermitted 中”permission串”在 realm 查询到权限数据中,说明用户访问 permission 串有权限,否则没有权限,抛出异常。
二、Shiro 的实现。
将Apache Shiro集成到基于Spring的应用程序中(SSM 实现)
独立应用程序
我是直接开发的 Web ,这里是官网标出来,我大概理解了一下。如有什么不对的地方,请见谅。
自定义的 Realm 必须继承 AuthorizingRealm,并实现两个 Abstract 方法 doGetAuthorizationInfo 和 doGetAuthenticationInfo。
页面的登录表单(Login Form)按照官方文档的写法,表单元素的名字都和文档一样(即:username、password 、rememberMe),表单登录(Login Action)只需要完成验证失败的跳转。验证成功变跳转至 successUrl。
默认的 FormAuthenticationFilter 会找这三个requestparameters:username、password 、rememberMe。设置FormAuthenticationFilter的这几个参数。authc.loginUrl = /login.html authc.usernameParam = adminNameauthc.passwordParam = adminPassauthc.rememberMeParam = addCookie
2.1、SSM 框架配置文件的方式 集成 Apache Shiro 。
SSM 框架 Shiro 的实现,请参考:https://blog.csdn.net/Roobert_Chao/article/details/89971383
2.2、Spring Boot 集成 Apache Shiro 。
Spring Boot 集成 Apache Shiro,请参考: https://blog.csdn.net/Roobert_Chao/article/details/89971828
Spring Boot 集成 Apache Shiro 并添加 Cache ,请参考:https://blog.csdn.net/Roobert_Chao/article/details/90046565
三、Shiro 的方法总结。
3.1、Shiro 支持三种方式的授权。
第一种,subject.hasRole(“admin”);主体中有admin权限?
Subject subject = SecurityUtils.getSubject();
if(subject.hasRole(“admin”)) {// 执行有权限的操作
} else {// 执行无权限的操作
}
第二种,<shiro:hasRole name=’’ > JSP页面的标签?
# 刚开始接触 Web 的时候,我只会写 JSP 页面。
<shiro:hasRole name="admin">
<!-- 有权限 -->
</shiro:hasRole>
第三种,学会使用注解之后进常用的。
# 注解式:通过在执行的Java方法上放置相应
@RequiresRoles("admin")
public void hello() {// 执行有权限的操作
}
3.2、@RequiresRoles 和 @RequiresPermissions 注解不生效。
- 上边,刚刚说过授权的第三种方式使用注解,但是注解必须必须要使用相应的bean才能生效。
- 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),
需借助SpringAOP扫描使用Shiro注解的类
,并在必要时进行安全逻辑验证,配置以下两个bean(DefaultAdvisorAutoProxyCreator
和AuthorizationAttributeSourceAdvisor
)。
# Shiro 权限注解要生效,必须配置 Spring AOP 通过设置 Shiro 的 SecurityManager 进行权限验证。
================= 注解的方式加入Bean ======================
@Beanpublic DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();advisorAutoProxyCreator.setProxyTargetClass(true); // 开启代理return advisorAutoProxyCreator;
}@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();authorizationAttributeSourceAdvisor.setSecurityManager(securityManager()); // 配置安全管理器。return authorizationAttributeSourceAdvisor;
}
================= 配置文件的方式加入 Bean ==================
<!-- 开启Shiro Spring AOP权限注解的支持;<aop:config proxy-target-class="true">表示代理类。 -->
<aop:config proxy-target-class="true">
<!-- 生命周期 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/><!-- 注解方式出现异常 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="org.apache.shiro.authz.UnauthorizedException">shiro-test/refuse</prop></props> </property>
</bean>
<!-- 认证用户的注解管理 -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"><property name="proxyTargetClass" value="true"/> <bean><!-- 授权用户的注解管理 -->
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"><property name="securityManager" ref="securityManager"/>
</bean>
### 拦截异常 。
@ExceptionHandler({UnauthorizedException.class})
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public ModelAndView processUnauthenticatedException(NativeWebRequest request, UnauthorizedException e) { ModelAndView mv = new ModelAndView(); mv.addObject("exception", e); mv.setViewName("unauthorized"); return mv;
}
3.3、Shiro 的注解。
- 注解既可以用在 controller 中,也可以用在 service 中使用。
建议将shiro注解放在 controller 中
,因为如果 service 层使用了spring的事物注解,那么 shiro 注解将无效。
@RequiresAuthentication
表示当前 Subject 已经通过 login 进行了身份验证;即 Subject.isAuthenticated() 返回true。
@RequiresUser
表示当前 Subject 已经身份验证或者通过记住我登录的。
@RequiresGuest
表示当前 Subject 没有身份验证或通过记住我登录过,即是游客身份。
@RequiresRoles(value={“admin”, “user”}, logical= Logical.AND)
@RequiresRoles(value={“admin”})
@RequiresRoles({“admin“})
表示当前 Subject 需要角色 admin 和 user。
@RequiresPermissions (value={“user:create”, “user:delete”}, logical= Logical.OR)
表示当前 Subject 需要权限 user:create 或 user:delete。
3.4、unauthorizedUrl 无效。
- <property name=“unauthorizedUrl” value="/unauthorized.html"/>
- shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
我们在测试之前,发现都起作用,但是在 SSM 框架整合之后,抛出异常,并没有跳转到无权限页面。原因是因为 页面的跳转交给springMVC来控制,权限认证不通过, SpringMVC 抛出了异常。
【方法一:注册 Bean SimpleMappingExceptionResolver 设置异常对应的 url,url 需要在 Controller 中指定
】
@Bean
public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();Properties properties = new Properties();/*未授权处理页*/properties.setProperty("org.apache.shiro.authz.UnauthorizedException", "/unauthor.html");/*身份没有验证*/properties.setProperty("org.apache.shiro.authz.UnauthenticatedException", "/login.html");resolver.setExceptionMappings(properties);return resolver;}
- 亲测可以。
【方法二:自定义异常类 Reslover 捕捉异常,如果异常为无权限异常就手动就是转发到无权页面。
】
1、首先设置异常的捕获类,
public class MyExceptionResolver implements HandlerExceptionResolver{public ModelAndView resolveException(HttpServletRequest request,HttpServletResponse response, Object handler, Exception e) {// 如果是shiro无权操作,因为shiro 在操作auno 等一部分不进行转发至无权限urlif(e instanceof UnauthorizedException){ModelAndView mv = new ModelAndView("unauthor");return mv;}e.printStackTrace();ModelAndView mv = new ModelAndView("unauthor");mv.addObject("exception", e.toString().replaceAll("\n", "<br/>"));return mv;}
}
2. 自定义异常处理
<bean id="exceptionResolver" class="cn.chao.formyself.resolver.MyExceptionResolver"></bean>
3.5、AJAX 请求,提示无角色无权限。
在上面的异常处理中,我们将判断一个请求,是否拥有角色的权限,无没有权限的话,则跳转到了无权限的页面中,那么我们要使用 AJAX 请求,返回的 error:function() 中应该是一个没有权限的提示信息。
【方法一:仍然使用第一种抛出异常的 Bean 。】
@Bean
public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();Properties properties = new Properties();/*未授权处理页*/properties.setProperty("org.apache.shiro.authz.UnauthorizedException", "/访问方法判断是否是 AJAX 处理");/*身份没有验证*/properties.setProperty("org.apache.shiro.authz.UnauthenticatedException", "/login.html");resolver.setExceptionMappings(properties);return resolver;}
【方法二:配置文件结合 Controller 层的代码判断】
配置异常的拦截器
<!-- shiro 为集成 springmvc 拦截异常 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"><property name="exceptionMappings" ><props><!-- 这里可以配置 N 多个 错误异常转发 --><prop key="org.apache.shiro.authz.AuthorizationException">redirect:/401</prop></property>
</bean>
异常拦截器将异常重定向到了 RequestMapping 401 的 controller 中
@RequestMapping("/401")
public String authorizationException(ModelMap modelMap,HttpServletRequest request){String requestType = request.getHeader("x-Requested-With");// AJAX 请求if(requestType != null && requestType.equals("XMLHttpRequest")){return "redirect:ajax401"; // 我在这里抛出的是权限的异常,判断为 AJAX 的请求方式,这里调用 RequestMapping("ajax401") 的方法,返回String 类型字符串,提示没有数据。}else{return "redirect:syn401"; // 方法体直接放回 无权限页面。}
}
SpringBoot 项目 Shiro 的实现相关推荐
- 在 SpringBoot 项目中,Spring Security 和 Shiro 该如何选择?
点击上方 好好学java ,选择 星标 公众号重磅资讯,干货,第一时间送达 今日推荐:推荐19个github超牛逼项目!个人原创100W +访问量博客:点击前往,查看更多 要知道Shiro和Sprin ...
- springboot项目中使用shiro 自定义过滤器和token的方式___shiro使用token登录流程
springboot项目中使用shiro 自定义过滤器和token的方式 实现步骤主要是以下几步: 1. 在项目中导入maven依赖 <dependency><groupId> ...
- springboot配置shiro多项目实现session共享的详细步骤
springboot配置shiro多项目实现session共享的详细步骤 公司需要这样的需求: 有两个项目master 主项目.suiteone 项目,两个项目各自由shiro 安全框架管理,当不能登 ...
- SpringBoot整合Shiro搭建登录注册认证授权权限项目模板
主要内容: 1 SpringBoot整合Shiro安全框架; 2 Shiro主要学习内容总结;(执行流程.主要对象接口.注意事项等) 3 Redis实现对权限信息缓存; ! 温馨提示: 想要快速搭Sh ...
- springboot+jwt+shiro+vue+elementUI+axios+redis+mysql完成一个前后端分离的博客项目(笔记,帮填坑)
根据B站up主MarkerHub视频制作的一个笔记 我的博客 B站博主链接: https://www.bilibili.com/video/BV1PQ4y1P7hZ?p=1 博主的开发文档: http ...
- SpringBoot整合Shiro安全框架完整实现
目录 一.环境搭建 1. 导入shiro-spring依赖 2. 编写首页及其controller 3. 编写shiro配置类 二.Shiro实现登录拦截 1. 编写页面及其controller 2. ...
- 这 5 个能挣钱的 SpringBoot 项目,真TMD香!
点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:又一程序员进了ICU:压垮一个家庭,一张结算单就够 个人原创100W+访问量博客:点击前往,查看更多 不得不佩服 ...
- SpringBoot+MyBatis+Shiro 搭建杂谈
点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:用好Java中的枚举,真的没有那么简单!个人原创+1博客:点击前往,查看更多 链接:https://www.cn ...
- SpringBoot整合Shiro实现登录认证和授权CHCache
文章目录 一. springboot实现普通登录 1 添加依赖 2 编写配置文件 3 新建实体类和mapper 4 编写业务层代码 5 编写控制器 6 编写启动类 7 编写登录页面和主页面 二. sp ...
最新文章
- 性能测试工具系列(一):性能测试工具对比分析
- 基于上一篇AS项目依赖库问题的优化解决方案
- 防止API被恶意调用,一般有哪些方法?
- jquey的parent()和parents()的区别
- 点击按钮抓不到页面的参数
- linux格式化外接硬盘命令,linux格式化硬盘命令
- Java 12字符串方法
- aliyun gradle 代理_gradle:现代高效的java构建工具
- openmeetings(开源视频会议系统)的详细安装步骤 (windows版)
- android 里程计算器,里程计算器
- 外国人申请在中国永久居留服务指南(中英文)
- 我的世界服务器修改地图,我的世界如何修改地图?
- 重装系统(win10企业版)
- spring cloud NetFlix 学习笔记
- opencv中的split函数
- Java实现 蓝桥杯 算法提高 成绩排名
- 专科学游戏建模好找工作嘛?
- 机械CAD设计中如何快速创建孔轴投影?
- fastlane自动化打包ipa并发布到firim或者蒲公英
- 电商网站运营之道:提升商品销量的新玩法