一.Shiro认证

1.ShiroFilter

ShiroFilter顾名思义就是Shiro的过滤器,它可以把在我们进行访问的url进行一个有无认证的过滤,比如说一些需要登录后才能进行访问的页面。

在我们的Shiro和Spring整合了之后,我们要配置ShiroFilter就需要在spring的applicationContext.xml文件中进行配置。

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager"/><property name="loginUrl" value="/login.jsp"/><property name="successUrl" value="/success.jsp"/><property name="unauthorizedUrl" value="/unauthorized.jsp"/><!--<property name="filterChainDefinitionMap" ref="filterChainDefinitionMap"></property>--><!--  配置哪些页面需要受保护. 以及访问这些页面需要的权限. 1). anon 可以被匿名访问2). authc 必须认证(即登录)后才可能访问的页面. 3). logout 登出.4). roles 角色过滤器--><property name="filterChainDefinitions"><value>/login.jsp = anon/shiro/login = anon/logout = logout/** = authc</value></property></bean>

其中这里要注意的是shiroFilter的id要和在web.xml中定义的 DelegatingFilterProxy的<filter-name>一致,因为spring是根据filter-name去IOC容器中寻找名字与filter-name一样的shiroFilter

<filter><filter-name>shiroFilter</filter-name><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class><init-param><param-name>targetFilterLifecycle</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>shiroFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

urls部分的配置:

其格式是“url=拦截器[参数]“,例如

        <property name="filterChainDefinitions"><value>/login.jsp = anon/shiro/login = anon/logout = logout/** = authc</value></property>

anon表示匿名访问,authc表示需要进行认证之后才能访问。

2.Shiro的认证流程

(1)账号认证

既然我们有些页面是已经过滤掉了(需要进行验证才能访问),那么shiro是怎样帮我们进行验证的尼?

其实认证我们用的是AuthenticatingRealm这个抽象类,实现doGetAuthticationInfo这个方法。

public class ShiroRealm extends AuthenticatingRealm {@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//把controller传过来的token中的username和password取出来UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;String username = usernamePasswordToken.getUsername();String password = "123456";if ("unknown".equals(username)) {throw new UnknownAccountException("该账号不存在");}if ("tom".equals(username)) {throw new LockedAccountException("该账号被冻结");}//参数1,principal: 认证的实体信息. 可以是 username, 也可以是数据表对应的用户的实体类对象.//参数2,credentials: 密码.//参数3,realmName: 当前 realm 对象的 name. 调用父类的 getName() 方法即可String realmName = getName();SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password,realmName);return simpleAuthenticationInfo;}
}

而我们的账号密码由controller那边传过来

@Controller
public class LoginController {@RequestMapping("/shiro/login")public String login(@RequestParam("username") String username, @RequestParam("password") String password) {Subject currentUser = SecurityUtils.getSubject();//如果当前用户没有被Shiro认证的话if (!currentUser.isAuthenticated()) {UsernamePasswordToken token = new UsernamePasswordToken(username, password);token.setRememberMe(true);try {//这里传过去的token会被Realm作为参数传入currentUser.login(token);}catch (AuthenticationException e){System.out.println("登录失败 : " + e);}}return "redirect:/success.jsp";}}

当然我们还要告诉shiro我们自定义的这个Realm,在spring的application.xml中声明

    <bean id="jdbcRealm" class="com.zyh.shiro.realms.ShiroRealm"></bean>

设置进securityManager中:

    <!--1. 配置 SecurityManager!-->     <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><property name="realm" ref="jdbcRealm"/></bean>

(2)密码的对比认证:

真正开发的时候我们的密码毫无疑问是从数据库中取出来的,取出来之后放进SimpleAuthticationInfo中然后进行比对,默认用的就是一个叫CredentialsMatcher的密码匹配器来进行前台和数据库密码的比对,但是数据库中存储的密码大多数都不可能是明文的,基本都是进过加密的密码,所以我们要进行密码比对的话,就要把前台传过来的密码也进行加密,然后再和数据库中查出来的加密密码进行比对,而怎么样在shiro中对密码进行加密?

我们需要配置一个HashCredentialsMatcher的密码匹配器,该密码匹配器能对封装的token中的password和数据库的password进行对比。

    <bean id="jdbcRealm" class="com.zyh.shiro.realms.ShiroRealm"><!--设置加密的密码匹配器--><property name="credentialsMatcher"><bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"><!--设置加密的方法--><property name="hashAlgorithmName" value="MD5"></property><!--设置加密的次数--><property name="hashIterations" value="1024"></property></bean></property></bean>

(3)配置多个Realm

在spring的配置文件中加入realms的属性:

    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><property name="cacheManager" ref="cacheManager"/><!--<property name="realm" ref="secondRealm"/>--><!--配置多个realm--><property name="authenticator" ref="authenticator"/><property name="realms" ><list><ref bean="jdbcRealm"></ref><ref bean="secondRealm"></ref></list></property><!--<property name="rememberMeManager.cookie.maxAge" value="10"></property>--></bean>

声明secondRealm:

    <bean id="secondRealm" class="com.zyh.shiro.realms.SecondRealm"><property name="credentialsMatcher"><bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"><property name="hashAlgorithmName" value="SHA1"></property><property name="hashIterations" value="1024"></property></bean></property></bean>

声明authenticator:

    <bean id="authenticator"class="org.apache.shiro.authc.pam.ModularRealmAuthenticator"><!--配置Realm的认证策略--><property name="authenticationStrategy"><!--至少有一个Realm认证成功的话就算是完全认证成功了--><bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean></property></bean>

说一下authenticator ,配置这个对象主要是用其中的认证策略属性,默认的认证策略是atLeastOneSuccessfulStrategy,表示至少有一个Realm认证成功就即可,将返回所有Realm身份验证成功的认证信息。

还有一个FirstSuccessfulStrategy:只要有一个 Realm 验证成功即可,只返回第一个 Realm 身份验证成功的认证信息,其他的忽略;

最后AllSuccessfulStrategy:所有Realm验证成功才算成功,且返回所有Realm身份验证成功的认证信息,如果有一个失败就失败了。

并且要注意的是如果没有一个Realm是认证成功的话会报错。

二.Shiro授权

1.过滤器配置角色或权限

虽然我们进行了账号密码的认证,但是有些页面需要一定的权限身份才能进行访问的。这时我们可以在过滤器中配置url = roles[参数]这样的格式

    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager"/><property name="loginUrl" value="/login.jsp"/><property name="successUrl" value="/success.jsp"/><property name="unauthorizedUrl" value="/unauthorized.jsp"/><!--roles[角色] 角色过滤器--><property name="filterChainDefinitions"><value>/login.jsp = anon/shiro/login = anon/logout = logout/user.jsp = roles[user]/admin.jsp = roles[admin]/** = authc</value></property></bean>

中括号里面的参数是角色,比如说有user这个角色才能访问user.jsp这个页面。

如果发现没有赋予权限的话将会重转发到unauthorized.jsp这个页面。

2.赋予角色

我们需要继承AuthorizingRealm这个授权类,该类是继承于AuthenticatingRealm这个认证类。我们重写里面的认证方法doGetAuthenticatingInfo方法和授权方法doGetAuthorizingInfo方法。所以以后我们自定义Realm的时候可直接继承于AuthoizingRealm这个类即可。

授权的具体逻辑上代码:

//授权时会调用此方法,访问一些限制了角色或者权限的url的时候调用(过滤器中的设置角色过滤器)@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("正在授权中...");//从PrincipalCollection中拿到登录用户的信息Object principal = principalCollection.getPrimaryPrincipal();//授予登录用户角色或权限System.out.println("principal:" + principal);Set<String> roles = new HashSet<>();roles.add("user");if ("admin".equals(principal)) {roles.add("admin");}//创建 SimpleAuthorizationInfo, 并设置其 roles 属性.SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);return info;}

首先拿到的是Principal,这个变量的值是从认证方法中传过来的

//第一个参数就是principal
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, realmName);

而用getPrimaryPrincipal拿到的是第一个Realm传过来的Principal,因为我们这里配置了两个Realm,而这个方法是按照配置的顺序来拿到第一个的Principal的。

然后设置该用户的角色,传进SimpleAuthorizationInfo对象中并返回。

        Set<String> roles = new HashSet<>();roles.add("user");if ("admin".equals(principal)) {roles.add("admin");}//创建 SimpleAuthorizationInfo, 并设置其 roles 属性.SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);

3.权限注解

在实际项目中我们通常都是使用注解来判断当前访问url的权限限制,主要有:

• @RequiresAuthentication:表示当前Subject已经通过login 进行了身份验证;即 Subject. isAuthenticated() 返回 true
• @RequiresUser:表示当前 Subject 已经身份验证或者通过记住我登录的。
• @RequiresGuest:表示当前Subject没有身份验证或通过记住我登录过,即是游客身份。
• @RequiresRoles(value={“admin”, “user”}, logical= Logical.AND):表示当前 Subject 需要角色 admin 和user
• @RequiresPermissions (value={“user:a”, “user:b”}, logical= Logical.OR):表示当前 Subject 需要权限 user:a 或user:b。

4.RememberMe

• Shiro 提供了记住我(RememberMe)的功能,比如访问如淘宝等一些网站时,关闭了浏览器,下次再打开时还是能记住你是谁,下次访问时无需再登录即可访问,基本流程如下:
• 1、首先在登录页面选中 RememberMe 然后登录成功;如果是浏览器登录,一般会把 RememberMe 的Cookie 写到客户端并
保存下来;
• 2、关闭浏览器再重新打开;会发现浏览器还是记住你的;
• 3、访问一般的网页服务器端还是知道你是谁,且能正常访问;
• 4、但是比如我们访问淘宝时,如果要查看我的订单或进行支付时,此时还是需要再进行身份认证的,以确保当前用户还是你

RememberMe和认证的区别:

• subject.isAuthenticated() 表示用户进行了身份验证登录的即使有 Subject.login 进行了登录;• subject.isRemembered():表示用户是通过记住我登录的,此时可能并不是真正的你(如你的朋友使用你的电脑,或者你的cookie 被窃取)在访问的• 两者二选一,即 subject.isAuthenticated()==true,则subject.isRemembered()==false;反之一样。

我们可以使用url = user这样的过滤器来进行过滤需要记住我才能访问的页面。也可以自己自定义RememberMeManager来设置RememberMe的cookie的有效时长(实际上设置了remenberme的话会多一个name为rememberme的cookie)来设置rememberme的有效期。

权限管理框架之Shiro相关推荐

  1. shiro 单点登录_Shiro权限管理框架(一):Shiro的基本使用

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

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

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

  3. Shiro权限管理框架详解

    1权限管理1.1什么是权限管理 基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权 ...

  4. Java shiro权限管理框架视频教程

    shiro权限管理框架视频教程 中级 共14课 权限系统在任何一个系统中都存在,随着分布式系统的大行其道,权限系统也趋向服务化,对于一个高级工程师来说,权限系统的设计是必不可少需要掌握的技术栈. 课程 ...

  5. C#session共享+redis_Shiro权限管理框架(二):Shiro结合Redis实现分布式环境下的Session共享...

    精品推荐 国内稀缺优秀Java全栈课程-Vue+SpringBoot通讯录系统全新发布! Docker快速手上视频教程(无废话版)[免费] 作者:夜月归途 转载自: https://www.cnblo ...

  6. Apache Shiro权限管理框架

    为什么80%的码农都做不了架构师?>>>    Apache Shiro 和Web项目集成 web.xml配置 <!-- Apache Shiro Filter-->&l ...

  7. shiro权限管理框架简介(一)

    一:什么是shiro? shiro是apache的一个开源框架,是一个权限管理的框架,实现 用户认证.用户授权. spring中有spring security (原名Acegi),是一个权限框架,它 ...

  8. 基于Spring+SpringMVC+Beetl的权限管理框架源码分享

    Java企业级开发平台源码 权限管理框架源码 源码分享! 基于Spring+SpringMVC+Beetl+Beetlsql+Shiro的权限管理框架.内置功能:用户管理.角色管理.菜单管理.字典管理 ...

  9. 基本权限管理框架,开通淘宝支付

    一直都想做一个后台权限管理框架,不需要太复杂的功能,满足一般需求即可,体积小巧,速度快,基本权限管理框架,就是这样的一个小型权限框架,至于你相不相信我不知道,反正我信!~~ 好吧,先上图,有图才有真像 ...

  10. 权限验证框架Shiro

    权限验证框架Shiro: Shiro简介 什么是Shiro: shiro是一个强大易用的Java安全框架,提供了认证,授权,加密,回话管理等功能: 认证(Authentication):用户身份识别, ...

最新文章

  1. Ping命令 参数介绍!
  2. Django REST framework API 指南(12):验证器
  3. 感情在钱面前一文不值,开公司谨记这6大规则
  4. PYTHON运维开发面试题整理
  5. 手机 省份证 归属地查询接口
  6. [To Selina] 《撒野》读后感
  7. Burpsuit2.0系列的破解 与jdk 1.80在ubuntu下运行成功.以及代理设置ok,且burp证书导入ok,却不能访问外网的问题.
  8. 站队(使用插入排序完成) (Standard IO)————c++插入排序
  9. PHP执行底层机制-zend详解
  10. c++获取umg ue_[UE4][V4.10]C++中定义UMG widget变量时的头文件引用有关问题
  11. 深度学习实战8-生活照片转化漫画照片应用
  12. qemu-img命令
  13. 虎牙Java后台实现三次面经
  14. 湖北武汉电信机房详细介绍
  15. Linux安装配置ssh 基于unbantu22.04.1 LTS版本
  16. context.Context
  17. 信息安全专家李钊博士:信息物理系统概述
  18. Ahmedabad公司的LiFi技术为Nadabet提供互联网接入能力
  19. 输入一个十进制数将它转换为八进制和十六进制数
  20. JVM学习笔记_垃圾收集器重要参数

热门文章

  1. 452.用最少数量的箭引爆气球
  2. python正则表达式模块re
  3. 2篇word文档比较重复率_【软件】PDF转word黑科技 快来get!
  4. java图的邻接表实现两种方式及实例应用分析
  5. 【带权并查集题目汇总】
  6. 使用JSPanda扫描客户端原型污染漏洞
  7. wifipumpkin3 WiFi钓鱼工具
  8. 数字的格式化c语言课程设计,【图片】发几个C语言课程设计源代码(恭喜自己当上技术小吧主)【东华理工大学吧】_百度贴吧...
  9. linux下apache安装ssl,linux下apache安装ssl步骤
  10. win7 mysql 未响应_求助啊 WIN7下安装mysql出问题 老是说未响应~!!