shiro使用(简单记住我/下次自动登录流程)附:cookie内容为deleteme的最终解决方法

既然要做,就做的细致一点,对得起自己!

写在前面:学过JSP的都知道,这种实现的方式就是cookie,就够了。

配置shiro.xml,配置cookie.

1.配置cookie的名字,存活时间以及其他

<bean id="cookieRememberMe" class="org.apache.shiro.web.servlet.simpleCookie">
  <constructor-arg name="name" value="rememberMeAfter"/>
  <!--cookie的存活时间-->
  <property name="maxAge" value="2592000"/>
  <!--请求是否为htt请求,防止恶意攻击-->
  <property name="httpOnly" value="true"/>
</bean>

2.将cookie注入到cookieRememberManager中

<bean id="cookieManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
  <property name="cookie" ref="cookieRememberMe"/>
  <!--cookie加密方式,至于下面的value的书写方式,属于Ognl表达式,T表示具体的类,后面跟类的完全限定名.方法名(参数)-->
  <perperty name="cipherKey" 
   value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}"/>
</bean>

3.将cookieManager添加到securityManager中

<bean id="securityManager" class=".shiro.web.mgt.DefaultWebSecurityManager"
        <!--1.在进入securityManager之后,执行权限验证和授权操作都是在realm中进行,所以这里要引 
        入我们自定义的realm-->
        <property name="realm" ref="customRealm"/>
        <!--2.配置登录时的记住我/下次自动登录选项-->
        <property name="rememberMeManager" ref="cookieManager"/>
        
</bean>

基本配置完成,在代码中,当我们根据用户是否勾选了记住我/下次自动登录选项,在subject.login(token)之前,加上一行代码,

token.setRememberMe(true/false),这样整个流程就基本走完

一个巨大的问题

测试cookie是否生效,结果,是不生效的,关闭浏览器,重新打开,还是需要登录。后台没有任何报错信息。

解决思路

 1.先看看后台是否返回cookie给浏览器了,在谷歌中找到cookie,如下图

可以看到,其中cookie确实是有我设置的cookie的名字,说明shiro.xml配置文件中没有错。注意下,这里的cookie的创建时间和失效时间是一样的,并且cookie的内容也不对,是deleteme.

2.去网上找帖子,找博文,只有一个博主和我有一样的问题,但是没有人提供回复。

3.没办法,只能去看源码。(以下为自己的解决思路

第一步:既然这个cookie内容为deleteme,肯定是哪里有错误,cookie的设置了一下,于是在simpleCookie中找,果然找到了

第二步:可以看到removeForm中进行了设置,在哪里调用的这个方法呢?simpleCookie中没有,shiro.xml是将simpleCookie交给了cookieRememberManager管理,于是进去找,结果,还真找到了。

forgetIdentity这个方法调用了removeForm这个方法,我的应该是第一个,因为我在认证过程中传的是Subject.这个方法又是在哪调用的呢?

第三步:CookieRememberMeManager中没有调用这个方法的,就去他继承的抽象类AbstractRememberManager中找,在这个抽象类中有一个onFailedLogin的方法,调用了它,于是debug,打断点,但是断点并没有进入onFailedLogin这个方法.瞬间懵逼,这咋整。

第四步:看了一大堆方法,也不知道干嘛的,看到了onSuccessfulLogin这个方法,打断点,看看进入了没,还真进去了。

这几步是顺序执行的,跟着断点走,一直到converPrincipalsToBytes这个方法的this.serialize这个位置,断点跟进去,发现有异常被捕获了,上面的try代码块涉及到了流的相关操作

看到这个提示和断点中的User实体类,我直接明白了,我的User实体类没有实现serializable接口,赶紧实现下接口。因为我自定义realm中关于认证的部分传的是User对象。这里如果你传的是String类型的username,则不会出问题,因为String实现了serializable接口。因为cookie是要返回给浏览器,保存在用户的硬盘里的,那么服务器给浏览器传的东西肯定是一个IO文件,既然涉及到IO,肯定涉及到流的操作,既然对象要实现流的input和output,那么肯定要实现serializable接口.看了源码之后才搞清楚,真是汗颜。

SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(authUser, password, getName());

第五步:重新测试,关闭浏览器,重新打开,可以不用验证直接登录。困扰的大问题终于解决。

经过这个坑,对shiro真是更加清楚了。

以下为这次跳坑之后,整理的shiro关于rememberMe的流程。

流程

1.shiro会先删除从浏览器获得cookie,并且初始化一个cookie,内容为deleteme.

2.relam认证成功之后,shiro视当前用户登录成功之后,调用onSuccessfulLogin方法,在DefaultSerializer类中将获得的principal对象通过对象流ObjectOutputStream写入到字节数组中。

3.第二步没有异常抛出的话则调用CookieRememberMeManager中的rememeberSerializedIdentity方法。如果第二步有异常,则会返回初始化的deleteMe的cookie,并且原来的cookie已经消失,因为第一步直接给删除了

4.rememeberSerializedIdentity方法中调用cookie.saeTo方法,直接设置对应的cookie返回给浏览器,如下图:

至此,一个小功能rememberMe完成。

 本专栏并没有提供相关完整的代码,不过,有一个前后端项目中整合了Shiro,如有需要,代码在这里

  • 12
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值