Shiro的 rememberMe 功能babun工具使用指导导为什么rememberMe设置了没作用

博客分类:
刚刚有一个网友 问我一个问题说他登录的时候 设置了
UsernamePasswordToken token = new UsernamePasswordToken(
currUser.getAccount(), currUser.getPwd());
token.setRememberMe(true);
然后 在登录方法里看到 token 对象里的isRememberMe()方法返回的也是true
为什么到其他action方法里 返回SecurityUtils.getSubject().isRemembered()是false?
起初我也很奇怪 难道他们是两个不同的 调用?
带着这个疑问我查看了 shiro的源码
我首先看了 登录方法里的set方法
实在UsernamePasswordToken.class类里的
* Returns &tt&true&/tt& if the submitting user wishes their identity (principal(s)) to be remembered
* across sessions, &tt&false&/tt& otherwise.
Unless overridden, this value is &tt&false&/tt& by default.
* @return &tt&true&/tt& if the submitting user wishes their identity (principal(s)) to be remembered
across sessions, &tt&false&/tt& otherwise (&tt&false&/tt& by default).
* @since 0.9
public boolean isRememberMe() {
return rememberMe;
* Sets if the submitting user wishes their identity (pricipal(s)) to be remembered across sessions.
* overridden, the default value is &tt&false&/tt&, indicating [i]not[/i] to be remembered across sessions.
* @param rememberMe value inidicating if the user wishes their identity (principal(s)) to be remembered across
* @since 0.9
public void setRememberMe(boolean rememberMe) {
this.rememberMe = rememberMe;
没看出什么
然后我进 boolean re=SecurityUtils.getSubject().isRemembered();
isRemembered();这个方法里看了下
发现是在Subject.class里面的
* {@link #getPrincipals() principals}, such as customized views, it should never perform highly-sensitive
* operations until the user has legitimately verified their identity by executing a successful authentication
* attempt.
* We see this paradigm all over the web, and we will use [url=][/url] as an
* example:
* When you
and perform a login and ask it to 'remember me', it will set a cookie with your
* identity.
If you don't log out and your session expires, and you come back, say the next day, Amazon still knows
* who you [i]probably[/i] are: you still see all of your book and movie recommendations and similar user-specific
* features since these are based on your (remembered) user id.
* BUT, if you try to do something sensitive, such as access your account's billing data, Amazon forces you
* to do an actual log-in, requiring your username and password.
* This is because
assumed your identity from 'remember me', it recognized that you were not
* actually authenticated.
The only way to really guarantee you are who you say you are, and therefore allow you
* access to sensitive account data, is to force you to perform an actual successful authentication.
* check this guarantee via the {@link #isAuthenticated() isAuthenticated()} method and not via this method.
* @return {@code true} if this {@code Subject}'s identity (aka {@link #getPrincipals() principals}) is
remembered from a successful authentication during a previous session, {@code false} otherwise.
* @since 1.0
boolean isRemembered();
点进去看实现方法是这样写的:
public boolean isRemembered() {
PrincipalCollection principals = getPrincipals();
return principals != null && !principals.isEmpty() && !isAuthenticated();
这样应该很清楚原因了 !
他的返回有三个条件 合并起来的 第一个和第二个都是一个意思 就是 该用户信息不为空,
第三个条件代表的意思是 当前用户是通过认证的!
因为我是刚刚登录不久& 肯定这个条件是为isAuthenticated();肯定是true
但是他前面加了一个感叹号("!")& 那合起来就是false了 三个条件 合起来
true&&true&&false
结果当然就是false
它的意思 就是& 因为该用户是 认证通过的所以是 false
我们可以回过头看看这两个标签的解释
user标签
认证通过或已记住的用户
&shiro:user&
Welcome back John!
Not John? Click &a href="login.jsp"&here&a& to login.
&/shiro:user&
authenticated标签
已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在。
&shiro:authenticated&
[url=updateAccount.jsp]Update your contact information[/url].
&/shiro:authenticated&
就是说 如果是 authc的情况下 是不能和user并存的 而user级别 恰恰就是 RememberMe =true
很多时候 我们遇到问题的时候往往先把自己往错误的地方带 往错误的方向去走
这样才会迷茫 ,我们要先弄懂 原因必须追根溯源
浏览: 419836 次
来自: 宁波
楼主 我想问下我是那个中文不换行的问题,你上面那个jar包 我 ...
q 写道你好 请教你一下
你有没有遇到方法 ...
大神在不,我这边生成完html转成PDF时中文直接没有了:
不 ...
做了好多个模板后客户要求加页码,这种方式导出pdf网上没找到解 ...
哥们,cas跨域的域名怎么单点登录啊! 比如A网站:www.a ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'网站配置未生效 |
| 百度云加速
请打开cookies.
你访问的网站() 使用了
网络。 百度云加速目前无法解析此域名 ().
主要因为: 网站主刚刚在百度云加速添加了这个域名,百度云加速需要几十秒的时间同步到全球网络中。稍等片刻刷新页面即可解决。
也有可能: 网站配置出错.博客分类:
使用shiro的时候,当我们使用remember me功能登录系统的时候,我们在用户登录自定义的session已经失效,这样就会影响系统正常运行;对于这种情况,我的解决方案是在shiro中自定义一个filter检测自定义的session是否失效,如果失效就读取数据加入到session中
shiro 配置文件:
&!-- 自定义加入filter,起在remember me session失效情况下刷新session作用 --&
&bean id="userSettingFilter" class="org.guess.security.filter.UserSetting" /&
在shiroFilter中加入该filter
&property name="filters"&
&util:map&
&entry key="userSetting" value-ref="userSettingFilter"/&
&/util:map&
&/property&
filter类代码:
public class UserSetting extends AccessControlFilter {
@Autowired
private UserService userS
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
Subject subject = getSubject(request, response);
if (subject == null) {
HttpSession session = ((HttpServletRequest)request).getSession();
User current_user = (User) session.getAttribute(Constants.CURRENT_USER);
Object recs = session.getAttribute(Constants.USER_MENUS);
//判断session是否失效,若失效刷新之
if(current_user == null || recs == null){
String username = (String) subject.getPrincipal();
User user = userService.findByLoginId(username);
session.setAttribute(Constants.CURRENT_USER, user);
session.setAttribute(Constants.USER_MENUS, user.getMenus());
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception {
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
求大师指导更好的解决方法
浏览 10095
浏览: 43983 次
来自: 成都
有人解决了类似的问题吗
你这session是HttpSession啊,不是shiro的 ...
是struts2的哪个版本啊?
可以伪造http头的x-forwarded-for参数值,发送 ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'博客分类:
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 id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie"&
&constructor-arg value="rememberMe"/&
&property name="httpOnly" value="true"/&
&property name="maxAge" value="2592000"/&&!-- 30天 --&
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"/&
rememberMe管理器,cipherKey是加密rememberMe Cookie的密钥;默认AES算法;
&!-- 安全管理器 --&
&bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"&
&property name="rememberMeManager" ref="rememberMeManager"/&
设置securityManager安全管理器的rememberMeManager;
&bean id="formAuthenticationFilter"
class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter"&
&property name="rememberMeParam" value="rememberMe"/&
rememberMeParam,即rememberMe请求参数名,请求参数是boolean类型,true表示rememberMe。
&bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"&
&property name="filterChainDefinitions"&
/login.jsp = authc
/logout = logout
/authenticated.jsp = authc
/** = user
&/property&
“/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使用过程中,需要配合相应的拦截器来实现相应的功能,用错了拦截器可能就不能满足你的需求了。
示例源代码:;可加群
探讨Spring/Shiro技术。
浏览 70842
shenjianhua1984 写道同一个用户登录多次,每次都会在cookie中带上rememberMe=...& 信息,多次登录后,我再用第一次返回的rememberMe信息,还是能访问系统?这个是不是有问题?另外看shiro的源码,对于rememberMe,服务端只是把PrincipalCollection序列化和反序列化并没有对反序列化后的凭证信息再次进行验证,就算服务器重启后,用之前的rememberMe信息还是能访问系统。还麻烦Tao哥答疑下,看是不是我的理解有问题?谢谢!恩,我这里也有这个问题。不知道有没有什么好的解决方案。这个问题我也有,我设置remember me为1分钟,把remember cookie保存下来,1分钟后原始页面cookie自动过期删除需要登录才能访问授权页面。但是我把提前保存的cookie再请求需授权页面则无需登录可以访问,即使我把服务器重启了还是能无需登录访问,说明remember me的cookie maxAge有效期服务端没有判断
同一个用户登录多次,每次都会在cookie中带上rememberMe=...& 信息,多次登录后,我再用第一次返回的rememberMe信息,还是能访问系统?这个是不是有问题?另外看shiro的源码,对于rememberMe,服务端只是把PrincipalCollection序列化和反序列化并没有对反序列化后的凭证信息再次进行验证,就算服务器重启后,用之前的rememberMe信息还是能访问系统。还麻烦Tao哥答疑下,看是不是我的理解有问题?谢谢!localhost 使用Set-Cookie无效,测试可以在hosts中配置一个域名
同一个用户登录多次,每次都会在cookie中带上rememberMe=...& 信息,多次登录后,我再用第一次返回的rememberMe信息,还是能访问系统?这个是不是有问题?另外看shiro的源码,对于rememberMe,服务端只是把PrincipalCollection序列化和反序列化并没有对反序列化后的凭证信息再次进行验证,就算服务器重启后,用之前的rememberMe信息还是能访问系统。还麻烦Tao哥答疑下,看是不是我的理解有问题?谢谢!恩,我这里也有这个问题。不知道有没有什么好的解决方案。
楼主好,我在测试这个例子的时候,并没有发现rememberMe的cookie,怎么回事呢?测试没有成功
涛 哥,我把web.xml 中的ContextLoaderListener和DelegatingFilterProxy都去了,为啥访问各个页面还是自动跳转到登录页面多次运行jetty:run 难道不是重启服务器吗?看控制台怎么有多个进程,把这些玩意儿都关了重启了一遍,能够看到改变的内容了,难道是这原因?
tao哥,访问http://localhost:8080/chapter13/ 跳转到登陆页面是哪里控制的?有点搞不清楚了 明白了,是shiroFilter的loginUrl控制的。另一个问题,如果shiroFilter和formAuthenticationFilter都设置了successUrl,表单成功登陆后会如何跳转呢?
jinnianshilongnian
浏览量:1736816
浏览量:2147862
浏览量:4329572
浏览量:177531
浏览量:1229767
浏览量:188270
浏览量:3699354
浏览量:450601
浏览量:475606
感谢楼主,你的文章给我很大的帮助。
Shiro异常1:java.lang.IllegalArgum ...
http://blog.csdn.net/u ...
http://blog.csdn.net/u ...
u 写道 写道Alex丿 写 ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'博客分类:
在学习shiro中遇到很多问题,网上资料较少,只有硬啃英文,但demo太少,不好理解。ITeye博客中开涛对编写了比较全的系列教程
,提供给大家学习,感谢开涛。
在学习到的时候,有一个问题困扰了我2天,给开涛留言,至今未回复,功夫不复有心人,今天早上得到了解决。
问题描述:
1.按照开涛的测试过程
测试: 1、访问http://localhost:8080/chapter13/,会跳转到登录页面,登录成功后会设置会话及rememberMe Cookie; 2、关闭浏览器,此时会话cookie将失效; 3、然后重新打开浏览器访问http://localhost:8080/chapter13/,还是可以访问的; 4、如果此时访问http://localhost:8080/chapter13/authenticated.jsp,会跳转到登录页面重新进行身份验证。
测试本章节demo时发现记住我功能不能实现,仔细思考为什么呢?
2.查看cookie,仅生成了sid的cookie,没有生成rememberMe,究竟哪里出了问题?
3.debug跟踪源码
public Subject login(Subject subject, AuthenticationToken token) throws
AuthenticationException {
AuthenticationI
info = authenticate(token);
} catch (AuthenticationException ae) {
onFailedLogin(token, ae, subject);
} catch (Exception e) {
if (log.isInfoEnabled()) {
("onFailedLogin method threw an " +
"exception.
Logging and propagating original
AuthenticationException.", e);
//propagate
Subject loggedIn = createSubject(token, info, subject);
onSuccessfulLogin(token, info, loggedIn);
return loggedIn;
从onSuccessfulLogin(token, info, loggedIn);这里一路逛追,直至
private javax.crypto.Cipher newCipherInstance(boolean streaming) throws
CryptoException {
String transformationString = getTransformationString(streaming);
return javax.crypto.Cipher.getInstance(transformationString);
} catch (Exception e) {
String msg = "Unable to acquire a Java JCA Cipher instance using " +
javax.crypto.Cipher.class.getName() + ".getInstance( \"" +
transformationString + "\" ). " +
getAlgorithmName() + " under this configuration is required
for the " +
getClass().getName() + " instance to function.";
throw new CryptoException(msg, e);
在这里 return javax.crypto.Cipher.getInstance(transformationString);抛出异常:
org.apache.shiro.crypto.CryptoException: Unable to acquire a Java JCA Cipher
instance using javax.crypto.Cipher.getInstance( "AES/CBC/PKCS5Padding" ).
AES under this configuration is required for the org.apache.shiro.crypto.
AesCipherService instance to function.
Caused by: java.security.NoSuchAlgorithmException: Cannot find any provider
supporting AES/CBC/PKCS5Padding
at javax.crypto.Cipher.getInstance(Cipher.java:523)
at org.apache.shiro.crypto.JcaCipherService.newCipherInstance
(JcaCipherService.java:408)
... 28 more
4.不明觉历!!!!!!!!!!!难道是开涛的代码有问题??还是故意设置了障碍要大家学习(实践证明这些假设都是错的)
5.网上查了很多资料,未果,分析源码CookieRememberMeManager继承了AbstractRememberMeManager,在AbstractRememberMeManager中的构造方法中默认初始化了加密算法与设置了默认的cipherKey
public AbstractRememberMeManager() {
this.serializer = new DefaultSerializer&PrincipalCollection&();
this.cipherService = new AesCipherService();
setCipherKey(DEFAULT_CIPHER_KEY_BYTES);
问题的结点可以定在cipherService的实现或者cipherKey的配置上,但很快排除了这一假设。
6.回顾第5章节的例子
public void testAesCipherService() {
CipherService cipherService = new AesCipherService();
// aesCipherService.setKeySize(128);//设置key长度
// byte[] key = aesCipherService.generateNewKey().getEncoded();
// String base64 = Base64.encodeToString(key);
byte[] key = Base64.decode("4AvVhmFLUs0KTA3Kprsdag==");
System.out.println("key2==" + key.toString());
System.out.println(Base64.encodeToString(key));
// 生成key
// Key key = aesCipherService.generateNewKey();
String text = "hello";
System.out.println(new String(text.getBytes()));
String encrptText = cipherService.encrypt(text.getBytes(
), key).toHex();
System.out.println("encrptText==" + encrptText);
String text2 = new String(cipherService.decrypt(
Hex.decode(encrptText), key).getBytes());
System.out.println("text2==" + text2);
Assert.assertEquals(text, text2);
} catch (CryptoException e) {
e.printStackTrace();
不断调试,右击项目属性--Properties----Java Build Path-----Libraries----JRE System Libraries,修改为jdk_1.7.0.01_x86(名称是添加jre时自定义的),测试代码,可以运行通过。原来是jdk的设置不正确!!!!我的电脑上安装了x86,x64的jdk,平时使用的是x64的版本。
7.以为大功告成,可是……使用jetty启动、使用tomcat启动,测试失败!啊啊啊!!要疯的节奏
8.难道是环境变量也要改过来?修改jdk环境变量%JAVA_HOME%为x86的版本之后,测试成功!终于松了一口气。
记录此问题的解决过程,虽然仅仅是jdk版本的问题,可能安装了x86 jdk的人永远不会遇到,但是还是费了我不少功夫去排除道道屏障,最终拨云见日。
1.shiro的加密使用javax.crypto.Cipher.getInstance获得实例,不支持64bit的jdk
2.遇到这个错误不用改环境变量,可以通过配置运行时的jre解决
a)tomcat:window-&perferences-&server-&runtime Env--Edit Server--修改JRE为x86版本
b)jetty:Debug As--Run Configurations---JRE修改为x86版本
(此问题为电脑上同时安装了x64、x86版本jdk的伙伴记录)
浏览: 258297 次
来自: 云南
我按你们说的也改成x86了,但还是报同样的错
完美解决,谢谢
看来 还是一步步跟,我也跟了,只是没有跟到你那么深
楼主有没有下载的hibernate中文版 chm的下载的文件啊 ...
挺全的,感谢作者
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'}

我要回帖

更多关于 就业指导中心多功能厅 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信