`
jinnianshilongnian
  • 浏览: 21424317 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2403176
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:2996176
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5630413
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:257187
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1592662
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:248795
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5845661
Group-logo
跟我学Nginx+Lua开...
浏览量:697478
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:779851
社区版块
存档分类
最新评论

第十三章 RememberMe——《跟我学Shiro》

阅读更多

 

目录贴: 跟我学Shiro目录贴

 

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

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

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

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

 

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

RememberMe配置

 

spring-shiro-web.xml配置:

<!-- 会话Cookie模板 -->
<bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
    <constructor-arg value="sid"/>
    <property name="httpOnly" value="true"/>
    <property name="maxAge" value="-1"/>
</bean>
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
    <constructor-arg value="rememberMe"/>
    <property name="httpOnly" value="true"/>
    <property name="maxAge" value="2592000"/><!-- 30天 -->
</bean> 

sessionIdCookie:maxAge=-1表示浏览器关闭时失效此Cookie;

rememberMeCookie:即记住我的Cookie,保存时长30天;

  

<!-- rememberMe管理器 -->
<bean id="rememberMeManager" 
class="org.apache.shiro.web.mgt.CookieRememberMeManager">
    <property name="cipherKey" value="
#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/>
     <property name="cookie" ref="rememberMeCookie"/>
</bean> 

rememberMe管理器,cipherKey是加密rememberMe Cookie的密钥;默认AES算法;

 

<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
……
    <property name="rememberMeManager" ref="rememberMeManager"/>
</bean> 

设置securityManager安全管理器的rememberMeManager; 

 

<bean id="formAuthenticationFilter" 
class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">
	……
    <property name="rememberMeParam" value="rememberMe"/>
</bean> 

rememberMeParam,即rememberMe请求参数名,请求参数是boolean类型,true表示rememberMe。 

 

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
	……
    <property name="filterChainDefinitions">
        <value>
            /login.jsp = authc
            /logout = logout
            /authenticated.jsp = authc
            /** = user
        </value>
    </property>
</bean> 

“/authenticated.jsp = authc”表示访问该地址用户必须身份验证通过(Subject. isAuthenticated()==true);而“/** = user”表示访问该地址的用户是身份验证通过或RememberMe登录的都可以。

 

测试:

1、访问http://localhost:8080/chapter13/,会跳转到登录页面,登录成功后会设置会话及rememberMe Cookie;

2、关闭浏览器,此时会话cookie将失效;

3、然后重新打开浏览器访问http://localhost:8080/chapter13/,还是可以访问的;

4、如果此时访问http://localhost:8080/chapter13/authenticated.jsp,会跳转到登录页面重新进行身份验证。

 

如果要自己做RememeberMe,需要在登录之前这样创建Token:UsernamePasswordToken(用户名,密码,是否记住我),如:

Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
token.setRememberMe(true);
subject.login(token); 

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

 

另外对于过滤器,一般这样使用:

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

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

 

因此RememberMe使用过程中,需要配合相应的拦截器来实现相应的功能,用错了拦截器可能就不能满足你的需求了。

 

示例源代码:https://github.com/zhangkaitao/shiro-example;可加群 231889722 探讨Spring/Shiro技术。

 

        

26
4
分享到:
评论
21 楼 mms 2017-11-22  
为啥我按照示例配置会出现如下错误:
java.lang.NoSuchFieldException: rememberMe
at java.lang.Class.getField(Class.java:1703)
        at org.springframework.beans.TypeConverterDelegate.attemptToConvertStringToEnum(TypeConverterDelegate.java:316)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:243)
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:93)
at org.springframework.beans.TypeConverterSupport.doConvert(TypeConverterSupport.java:64)
20 楼 xiao明123 2017-04-19  
WARN  [org.apache.shiro.mgt.AbstractRememberMeManager] - There was a failure while trying to retrieve remembered principals.  This could be due to a configuration problem or corrupted principals.  This could also be due to a recently changed encryption key, if you are using a shiro.ini file, this property would be 'securityManager.rememberMeManager.cipherKey' see: http://shiro.apache.org/web.html#Web-RememberMeServices. The remembered identity will be forgotten and not used for this request.
  2017-04-19 13:54:03,488 [qtp763610533-19] WARN  [org.apache.shiro.mgt.DefaultSecurityManager] - Delegate RememberMeManager instance of type [org.apache.shiro.web.mgt.CookieRememberMeManager] threw an exception during getRememberedPrincipals().
  org.apache.shiro.io.SerializationException: Unable to deserialze argument byte array.
at org.apache.shiro.io.DefaultSerializer.deserialize(DefaultSerializer.java:82)
at org.apache.shiro.mgt.AbstractRememberMeManager.deserialize(AbstractRememberMeManager.java:507)

.......

Caused by: java.io.StreamCorruptedException: invalid type code: 00
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1379)
at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1682)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1345)
at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1993)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1918)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1801)


这是怎么回事啊 
19 楼 liaqing 2017-04-17  
<!-- rememberMe管理器 --> 
<bean id="rememberMeManager"  
class="org.apache.shiro.web.mgt.CookieRememberMeManager"> 
    <property name="cipherKey" value=" 
#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/> 
     <property name="cookie" ref="rememberMeCookie"/> 
</bean>  


为什么会报错
Caused by: java.security.InvalidKeyException: Invalid AES key length: 60 bytes
18 楼 flyChan 2017-02-21  
请问cipherKey是不是可以任意修改?还是说需要用什么算法进行生成?
17 楼 纵观全局 2016-09-13  
已经有cookie了 ,也可以登陆其他页面了 。就是直接项目名出404   ,没有登陆的时候是跳转到login页面。现在有cookie了,为啥不能到指定页面
16 楼 yhqnh 2016-07-17  
lovebird321 写道
shenjianhua1984 写道
同一个用户登录多次,每次都会在cookie中带上rememberMe=...  信息,多次登录后,我再用第一次返回的rememberMe信息,还是能访问系统?这个是不是有问题?
另外看shiro的源码,对于rememberMe,服务端只是把PrincipalCollection序列化和反序列化
并没有对反序列化后的凭证信息再次进行验证,就算服务器重启后,用之前的rememberMe信息还是能访问系统。


还麻烦Tao哥答疑下,看是不是我的理解有问题?谢谢!



恩,我这里也有这个问题。不知道有没有什么好的解决方案。



这个问题我也有,我设置remember me为1分钟,把remember cookie保存下来,1分钟后原始页面cookie自动过期删除需要登录才能访问授权页面。
但是我把提前保存的cookie再请求需授权页面则无需登录可以访问,即使我把服务器重启了还是能无需登录访问,说明remember me的cookie maxAge有效期服务端没有判断
15 楼 a623939400 2016-05-18  
开启rememberMe后修改密码,之前的cookie并不会失效。
请问如何解决?
14 楼 aboutyang 2015-11-17  
shenjianhua1984 写道
同一个用户登录多次,每次都会在cookie中带上rememberMe=...  信息,多次登录后,我再用第一次返回的rememberMe信息,还是能访问系统?这个是不是有问题?
另外看shiro的源码,对于rememberMe,服务端只是把PrincipalCollection序列化和反序列化
并没有对反序列化后的凭证信息再次进行验证,就算服务器重启后,用之前的rememberMe信息还是能访问系统。


还麻烦Tao哥答疑下,看是不是我的理解有问题?谢谢!



localhost 使用Set-Cookie无效,测试可以在hosts中配置一个域名
13 楼 Daniel_yexi 2015-09-08  
设置了shiro的rememberMe ,tomcat设置了默认登录项目,我写了一个过滤器是在登录界面之前验证有没有之前做了记住密码操作的。但是tomcat设置默认项目之后尽管我有记住密码但是都是验证不通过,但是打完全名就是把项目名也打上就可以。。求解!
12 楼 lovebird321 2015-08-11  
shenjianhua1984 写道
同一个用户登录多次,每次都会在cookie中带上rememberMe=...  信息,多次登录后,我再用第一次返回的rememberMe信息,还是能访问系统?这个是不是有问题?
另外看shiro的源码,对于rememberMe,服务端只是把PrincipalCollection序列化和反序列化
并没有对反序列化后的凭证信息再次进行验证,就算服务器重启后,用之前的rememberMe信息还是能访问系统。


还麻烦Tao哥答疑下,看是不是我的理解有问题?谢谢!



恩,我这里也有这个问题。不知道有没有什么好的解决方案。
11 楼 shenjianhua1984 2015-07-09  
同一个用户登录多次,每次都会在cookie中带上rememberMe=...  信息,多次登录后,我再用第一次返回的rememberMe信息,还是能访问系统?这个是不是有问题?
另外看shiro的源码,对于rememberMe,服务端只是把PrincipalCollection序列化和反序列化
并没有对反序列化后的凭证信息再次进行验证,就算服务器重启后,用之前的rememberMe信息还是能访问系统。


还麻烦Tao哥答疑下,看是不是我的理解有问题?谢谢!

10 楼 天明破晓 2015-06-27  
天明破晓 写道
楼主好,我在测试这个例子的时候,并没有发现rememberMe的cookie,怎么回事呢?

测试没有成功
9 楼 天明破晓 2015-06-27  
楼主好,我在测试这个例子的时候,并没有发现rememberMe的cookie,怎么回事呢?
8 楼 fan7421436 2014-07-14  
UsernamePasswordToken token = null;
if (!subject.isAuthenticated() && subject.isRemembered()) {
Object principal = subject.getPrincipal();
if (null != principal) {
Member mem = (Member) principal;
token = new UsernamePasswordToken(mem.getAccountName(),
mem.getLoginPassword());
token.setRememberMe(true);
subject.login(token);// 登录
}
} else {

               //省略代码-里面是一个新的token 生成
}

-----------------
我看我们同事这样写的,没有在shiro里面配置,也实现了记住我的功能。关闭浏览器重新打开,也做到了
7 楼 fan7421436 2014-07-14  
UsernamePasswordToken token = null;
if (!subject.isAuthenticated() && subject.isRemembered()) {
Object principal = subject.getPrincipal();
if (null != principal) {
Member mem = (Member) principal;
token = new UsernamePasswordToken(mem.getAccountName(),
mem.getLoginPassword());
token.setRememberMe(true);
subject.login(token);// 登录
}
} else {

}
6 楼 z19910509 2014-04-01  
z19910509 写道
涛 哥,我把web.xml 中的ContextLoaderListener和DelegatingFilterProxy都去了,为啥访问各个页面还是自动跳转到登录页面


多次运行jetty:run 难道不是重启服务器吗?看控制台怎么有多个进程,把这些玩意儿都关了重启了一遍,能够看到改变的内容了,难道是这原因?
5 楼 z19910509 2014-04-01  
涛 哥,我把web.xml 中的ContextLoaderListener和DelegatingFilterProxy都去了,为啥访问各个页面还是自动跳转到登录页面
4 楼 Crazyliuxj 2014-03-20  
Crazyliuxj 写道
tao哥,访问http://localhost:8080/chapter13/ 跳转到登陆页面是哪里控制的?有点搞不清楚了

明白了,是shiroFilter的loginUrl控制的。另一个问题,如果shiroFilter和formAuthenticationFilter都设置了successUrl,表单成功登陆后会如何跳转呢?
3 楼 Crazyliuxj 2014-03-20  
tao哥,访问http://localhost:8080/chapter13/ 跳转到登陆页面是哪里控制的?有点搞不清楚了
2 楼 loveli 2014-03-19  
终于有人出shiro的专栏了,官方文档讲的内容有点儿少,没多少示例。spring security和shiro,单都是停留在会使用的层面。继续关注您的专栏,期待后面的文章……

相关推荐

Global site tag (gtag.js) - Google Analytics