Shiro框架:缓存、session会话、自定义FormAuthenticationFilter、RemenberMe

Shiro框架:缓存、session会话、自定义FormAuthenticationFilter、RemenberMe

上篇的地址:https://blog.csdn.net/a745233700/article/details/81350191

 

一、Shiro缓存–cacheManager:

针对上一篇授权的时候频繁查询数据库的问题,可以使用shiro缓存来解决。

1、缓存流程:

(1)shiro中提供了对认证信息和授权信息的缓存。shiro默认是关闭认证信息缓存的,对于授权信息的缓存shiro默认开启的。我们主要研究授权信息缓存,因为授权的数据量大。

(2)流程:用户认证通过之后,该用户第一次授权;调用realm查询数据库。该用户第二次授权,不调用realm查询数据库,直接从缓存中取出授权信息(权限标识符)。

2、配置shiro缓存:

(1)导入依赖:

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

(2)配合cacheManager:

    <!-- securityManager安全管理器 -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="customRealm"></property>
		<!-- 注入缓存管理器 -->
		<property name="cacheManager" ref="cacheManager"></property>
	</bean>
	
	<!-- 缓存管理器 -->
	<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
		<property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"></property>
	</bean>

(3)编写缓存相关信息文件:shiro-ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
	<!--diskStore:缓存数据持久化的目录 地址  -->
	<diskStore path="D:\test\shiro\ehcache" />
	<defaultCache 
		maxElementsInMemory="1000" 
		maxElementsOnDisk="10000000"
		eternal="false" 
		overflowToDisk="false" 
		diskPersistent="false"
		timeToIdleSeconds="120"
		timeToLiveSeconds="120" 
		diskExpiryThreadIntervalSeconds="120"
		memoryStoreEvictionPolicy="LRU">
	</defaultCache>
</ehcache>

至此,Shiro的缓存就配置好了。

3、缓存清空:

(1)如果用户正常退出,缓存自动清空;如果用户非正常退出,缓存也自动清空。

如果修改了用户的权限,而用户不退出系统,修改的权限无法立即生效。

(2)手动进行编程的实现:

在权限修改后,调用realm的clearCache方法清除缓存。

下边的代码正常开发时要放在service中调用。

在service中,权限修改后调用realm的方法。

在realm中定义clearCached方法:

    //清除缓存代码
    public void clearCached() {
		PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
		super.clearCache(principals);
	}

(3)测试清除缓存的controller方法:

@Controller
public class ClearShiroCacheTest {

	//注入realm
	@Autowired
	private CustomRealm customRealm;
	
	@RequestMapping("/clearShiroCache")
	public String clearShiroCache(){
		//清除缓存,在正常开发中要在service
		customRealm.clearCached();
		
		return "success";
	}
}

4、shiro缓存说明:

(1)CacheManagerAware接口:

Shiro内部相关组件(DefaultSecurityManager)会自动检测相应的对象(如Realm)是否实现了CacheManagerAware并自动注入了CacheManager。

(2)Realm缓存:Shiro提供了CachingRealm,其实现了CacheManagerAware接口,提供了一些基础实现;并且,AuthenticationRealm和AuthorizingRealm也分别提供了AuthenticationInfo和AutuorizationInfo信息的缓存。

 

 

二、Shiro会话–sessionManager:

SSM和Shiro整合后,使用shiro的session管理,shiro提供sessionDao操作会话数据。

1、Shiro提供了完整的企业级会话管理功能,不依赖于底层容器(如web容器tomcat),不管JavaSE还是JavaEE环境都可以使用,提供了会话管理、会话事件监听、会话存储/持久化、容器无关的集群、失效/过期支持、对Web 的透明支持、SSO 单点登录的支持等特性。

2、配置sessionManager:

	<!-- securityManager安全管理器 -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="customRealm"></property>
		<!-- 注入缓存管理器 -->
		<property name="cacheManager" ref="cacheManager"></property>
		<!-- 注入session管理器 -->
		<property name="sessionManager" ref="sessionManager"></property>
	</bean>
	
	<!-- 会话管理器 -->
	<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
		<!-- session的失效时间,单位毫秒 -->
		<property name="globalSessionTimeout" value="600000"></property>
		<!-- 删除失效的session -->
		<property name="deleteInvalidSessions" value="true"></property>
	</bean>

3、会话相关的API:

(1)Subject.getSession():即可获取会话;其等价于Subject.getSession(true),即如果当前没有创建Session 对象会创建一个;Subject.getSession(false),如果当前没有创建Session 则返回null。

(2)session.getId():获取当前会话的唯一标识。

(3)session.getHost():获取当前Subject的主机地址

(4)session.getTimeout() & session.setTimeout(毫秒):获取/设置当前Session的过期时间。

(5)session.getStartTimestamp() & session.getLastAccessTime():获取会话的启动时间及最后访问时间;如果是JavaSE应用需要自己定期调用session.touch() 去更新最后访问时间;如果是Web 应用,每次进入ShiroFilter都会自动调用session.touch() 来更新最后访问时间。

(6)session.touch() & session.stop():更新会话最后访问时间及销毁会话;当Subject.logout()时会自动调用stop 方法来销毁会话。如果在web中,调用HttpSession. invalidate() 也会自动调用ShiroSession.stop方法进行销毁Shiro的会话。

(7)session.setAttribute(key, val) & session.getAttribute(key) & session.removeAttribute(key):设置/获取/删除会话属性;在整个会话范围内都可以对这些属性进行操作。

 

 

三、自定义FormAuthenticationFilter:

1、需求:使用自定义的FormAuthenticationFilter实现验证码功能。

(1)shiro使用FormAuthenticationFilter进行表单认证,验证校验的功能应该加在FormAuthenticationFilter中,在认证之前进行验证码校验。

(2)需要写FormAuthenticationFilter的子类,继承FormAuthenticationFilter,改写它的认证方法,在认证之前进行验证码校验。

2、自定义FormAuthenticationFilter:

/**
 * Description:自定义FormAuthenticationFilter,认证之前实现 验证码校验 
 */
public class CustomFormAuthenticationFilter extends FormAuthenticationFilter {

	//原FormAuthenticationFilter的认证方法
	@Override
	protected boolean onAccessDenied(ServletRequest request,
			ServletResponse response) throws Exception {
		//在这里进行验证码的校验
		//从session获取正确验证码
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
		HttpSession session =httpServletRequest.getSession();
		//取出session的验证码(正确的验证码)
		String validateCode = (String) session.getAttribute("validateCode");
		
		//取出页面的验证码
		//输入的验证和session中的验证进行对比 
		String randomcode = httpServletRequest.getParameter("randomcode");
		if(randomcode!=null && validateCode!=null && !randomcode.equals(validateCode)){
			//如果校验失败,将验证码错误失败信息,通过shiroLoginFailure设置到request中
			httpServletRequest.setAttribute("shiroLoginFailure", "randomCodeError");
			//拒绝访问,不再校验账号和密码 
			return true; 
		}
		return super.onAccessDenied(request, response);
	}
}

3、配置自定义FormAuthenticationFilter:

	<!-- 自定义form认证过滤器 -->
	<!-- 基于form表单的身份验证过滤器,不配置也会注册此过滤器,不过表单中的用户账号、密码和loginUrl将采用默认值,建议配置 -->
	<bean id="formAuthenticationFilter" class="com.zwp.shiro.CustomFormAuthenticationFilter">
		<!-- 表单中账户的input名称 -->
		<property name="usernameParam" value="username"></property>
		<!-- 表单中密码的input名称 -->
		<property name="passwordParam" value="password"></property>
	</bean>

Shiro框架:缓存、session会话、自定义FormAuthenticationFilter、RemenberMe

4、在登陆页面添加验证码:

Shiro框架:缓存、session会话、自定义FormAuthenticationFilter、RemenberMe

5、在filter配置匿名访问验证码的jsp:

Shiro框架:缓存、session会话、自定义FormAuthenticationFilter、RemenberMe

至此,使用自定义FormAuthenticationFilter实现验证码功能就完成了。

 

 

四、记住我–RememberMe:

1、概述:Shiro提供了记住我(RememberMe)的功能,比如访问如淘宝等一些网站时,关闭了浏览器,下次再打开时还是能记住你是谁,下次访问时无需再登录即可访问,基本流程如下:

(1)首先在登录页面选中RememberMe然后登录成功;如果是浏览器登录,一般会把RememberMe的Cookie 写到客户端并保存下来;

(2)关闭浏览器再重新打开;会发现浏览器还是记住你的;

(3)访问一般的网页服务器端还是知道你是谁,且能正常访问;

(4)但是比如我们访问淘宝时,如果要查看我的订单或进行支付时,此时还是需要再进行身份认证的,以确保当前用户还是你。

2、认证和记住我:

(1)subject.isAuthenticated() 表示用户进行了身份验证登录的,即使有Subject.login进行了登录;

(2)subject.isRemembered():表示用户是通过记住我登录的,此时可能并不是真正的你(如你的朋友使用你的电脑,或者你的cookie 被窃取)在访问的。

(3)两者二选一,即subject.isAuthenticated()==true,则subject.isRemembered()==false;反之一样。

3、实现:

用户登陆选择“记住我”,本次登陆成功会向cookie写身份信息,下次登陆从cookie中取出身份信息实现自动登陆。

(1)用户身份实现java.io.Seriializable接口:

向cookie记录身份信息,需要用户身份信息对象实现序列化接口,如下:

/**
 * 用户身份信息,存入session,由于tomcat将session序列化在本地硬盘上,所以使用Serializable接口
 */
public class ActiveUser implements java.io.Serializable {
	private String userid;//用户id(主键)
	private String usercode;// 用户账号
	private String username;// 用户名称

	private List<SysPermission> menus;// 菜单
	private List<SysPermission> permissions;// 权限
	
	//下面省略set和get方法
}

(2)配置rememberMeManager:

	<!-- securityManager安全管理器 -->
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="realm" ref="customRealm"></property>
		<!-- 注入缓存管理器 -->
		<property name="cacheManager" ref="cacheManager"></property>
		<!-- 注入session管理器 -->
		<property name="sessionManager" ref="sessionManager"></property>
		<!-- 记住我,注入 -->
		<property name="rememberMeManager" ref="rememberMeManager"></property>
	</bean>
	
	<!-- rememberMeManager管理器,取出cookie生成用户信息 -->
	<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
		<property name="cookie" ref="rememberMeCookie"></property>
	</bean>
	
	<!-- 记住我cookie -->
	<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
		<!-- remenberMe是cookie的名字 -->
		<constructor-arg value="rememberMe"></constructor-arg>
		<!-- remenberMe的cookie的生效时间是30天 -->
		<property name="maxAge" value="2592000"></property>
	</bean>

(3)登陆页面:

Shiro框架:缓存、session会话、自定义FormAuthenticationFilter、RemenberMe

(4)配置rememberMe的名称:

Shiro框架:缓存、session会话、自定义FormAuthenticationFilter、RemenberMe

(5)测试:

勾选“记住我”登陆后,查看cookie是否有rememberMe:

Shiro框架:缓存、session会话、自定义FormAuthenticationFilter、RemenberMe

(6)使用UserFilter:

如果设置记住我,下次访问某些url时可以不用登陆。将记住我即可访问的地址配置让UserFilter拦截。

Shiro框架:缓存、session会话、自定义FormAuthenticationFilter、RemenberMe

至此,Shiro的rememberMe就配置完成了。

(7)remenberMe使用建议:

①访问一般网页:如个人在主页之类的,我们使用user 拦截器即可,user 拦截器只要用户登录(isRemembered() || isAuthenticated())过即可访问成功;

②访问特殊网页:如我的订单,提交订单页面,我们使用authc拦截器即可,authc拦截器会判断用户是否是通过Subject.login(isAuthenticated()==true)登录的,如果是才放行,否则会跳转到登录页面叫你重新登录。

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/114708.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • leetcode 接雨水2_leetcode会议室

    leetcode 接雨水2_leetcode会议室题目链接给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。示例 1:输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]输出:6解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。示例 2:输入:height = [4,2,0,3,2,5]输出:9 提示:n == height.length0 <= n &lt

  • 《数字图像处理原理与实践(MATLAB版)》一书之代码Part2[通俗易懂]

    《数字图像处理原理与实践(MATLAB版)》一书之代码Part2

  • 反三角函数在线计算机,反三角函数(反正弦,反余弦,反正切,反余切,反正割,反余割)在线计算器_三贝计算网_23bei.com…[通俗易懂]

    输入已知数据点计算按钮,可求出对应的角度值、弧度值、反正弦arcsin、反余弦arcos、反正切artan、反余切arcot、反正割arsec、反余割arcsc等值。为限制反三角函数为单值函数,将反正弦函数的值y限在-π/2≤y≤π/2,将y作为反正弦函数的主值,记为y=arcsinx;相应地,反余弦函数y=arccosx的主值限在0≤y≤π;反正切函数y=arctanx的主值限在-π/2余…

  • tcp拥塞控制机制

    tcp拥塞控制机制为了防止网络的拥塞现象,TCP提出了一系列的拥塞控制机制.主要包括以下几个:1:慢启动(Slowstart)2:拥塞避免(Congestionavoidance)3:快速重传(Fastretransmit)4:快速恢复(FastRecovery)5:选择性应答(selectiveacknowledgement,SACK)算法TCP的拥塞控制主要原理依赖于一个拥塞窗口…

  • pycharm 打不开了_pycharm激活成功教程之后打不开

    pycharm 打不开了_pycharm激活成功教程之后打不开pycharm打不开问题总结1:第一步:进入如下路径,找到cmd.exe,右键选择“以管理员身份运行”;第二步:在打开的cmd窗口中,输入netshwinsockreset,按回车键;第三步:重启电脑;第四步:重启后,双击pycharm图标就能打开了!2:你下载的应该是官方版的,然后自己加了网上下载的.jar激活成功教程插件,并添加了这个插件的路径到.vmoptions文件。打不开是因为你修改…

  • 数据库 之 关系模式范式

    数据库 之 关系模式范式主要有6种范式:第一范式(1NF),第二范式(2NF),第三范式(3NF),巴德斯科范式(BCNF),第四范式(4NF),第五范式(5NF),按从左至右的顺序一种比一种要求更严格。要符合某一种范式必须

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号