记住我remember-me功能的几种实现方式

        本文讨论几种记住我功能的实现方式。

        原理:用户登录后,服务端为用户生成一个Token,并放入客户端Cookie中。下次用户登录,服务端验证Cookie中的Token并自动登录。

  • 简单的Token生成方法
            Token=MD5Hex(username+分隔符+expiryTime+分隔符+password)
            CookieValue=Base64(username+分隔符+expiryTime+分隔符+Token)
            username:用户名。
            password:用户密码。
            expiryTime:Token的失效时间,以毫秒表示。

            该方法生成的Token不需要持久化,每次生成时失效时间不同,可保证Token不同(也可以在Token中增加一些变量,如系统配置的key)。用户第一次登陆时生成Token;第二次打开系统时,根据CookieValue中username查询数据库,并重新生成Token,验证用户提交Token是否正确,如果正确成功登入系统,如果不正确,调整到登陆页面。

            存在安全问题。当用户Cookie被窃取(HttpOnly增加安全性),任何用户都可以在Token失效之前登录。发现被盗用,可以修改password来使Token失效,或者系统在用户每次登入系统时都重新生成Token。

            缺点:由于Token没有持久化,所以需要从已知的变量(如username、password、expiryTime)重新生成来验证,password即使加密放入前台,也不是一个好的解决方法。纵然不使用password,也需要其他变量来保证Token的可靠性。

  • 持久化的Token生成方法

            Token的生成规则可以自定义,只要保证每次username的Token不一样就可,例如采用16位随机数(如Java的SecureRandom)。规则同上面类似,只是将Token与用户信息解耦。但是安全问题依旧存在。

  • 持久化Token生成方法并验证Cookie是否被窃取
            Token:随机生成策略,只要保证username唯一性。
            series:登录序列号,随机生成策略。用户输入用户名和密码登录时,该值重新生成。使用remember-me功能,该值保持不变,重新生成Token。
             expiryTime:Token过期时间。
            1)每次用户选择记住我并登录后,都重新随机生成series、Token,保存到数据库和前端Cookie中。
            2)下一次用户再次访问系统,情况一:前台Cookie中保存的series值在数据库中不存在,跳转到登录页面。情况二:series、Token与数据库中一致,则仍为合法用户,并保持series不变,重新随机生成Token,覆盖前台Cookie值。情况三:series在数据库中存在,但Token不一致,说明Cookie被窃取。


情况一、同用户相同浏览器访问系统
步骤
用户A浏览器
1 A登录成功,series=seriesA,token=tokenA
2 在Token失效之前该浏览器访问系统,合法,生成series=seriesA,token=tokenB。
3 Token失效,或者用户重新登录,生成series=seriesB,token=tokenC

情况二、同用户不同浏览器访问系统

步骤
用户A浏览器X
用户A浏览器Y
1 浏览器X登录成功,series=seriesA,token=tokenA  
2   浏览器Y访问,无series信息,用户重新登录,series=seriesB,token=tokenB
3 浏览器X再次问题,seriesA失效,需要重新登录  


情况三、Cookie被盗
步骤 用户A 黑客B
1 A登录成功,生成series=seriesA,token=tokenA  
2   盗取A Cookie,使用series=seriesA,token=tokenA登入系统成功,重新生成series=seriesA,token=tokenB
3 A再次访问,发现serieA相同,但是Token不同,提醒用户Cookie被盗  

              安全问题依然存在。当然,可以考虑用户访问等级,如用户名密码登录级别最高,而对于Token记住我登录次之,对于一些重要的业务操作时(如支付),还是需要进行用户身份认证。
            还可以考虑用户IP,但现在移动用户,经常切换WiFi和网络,所以IP也会发生变化。例如手机银行(如招行客户端)切换网络后,需要重新登录,提高安全性。
            还可以考虑,用户常用IP、城市等安全策略。

            还有Shiro也实现了该记住我功能,但是本人没有使用过,等退后学习了再来更新。













  • 9
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Spring Security提供了Remember-me功能来让用户在下次访问时无需重新登录。要启用Remember-me功能,可以按照以下步骤进行配置: 1. 在Spring Security配置文件中启用Remember-me功能,例如: ``` http .rememberMe() .key("remember-me-key") .rememberMeParameter("remember-me") .tokenValiditySeconds(86400) .userDetailsService(userDetailsService); ``` 其中,key是用来加密Remember-me cookie的密钥,rememberMeParameter是用来接收Remember-me cookie的请求参数,tokenValiditySeconds是Remember-me cookie的有效期,userDetailsService是用来根据用户名获取用户信息的服务。 2. 在登录页面中添加Remember-me的复选框,例如: ``` <input type="checkbox" name="remember-me" value="true" /> Remember me ``` 3. 在登录成功后生成Remember-me cookie,例如: ``` @RequestMapping(value = "/login", method = RequestMethod.POST) public String login(@RequestParam("username") String username, @RequestParam("password") String password, @RequestParam(value = "remember-me", required = false) boolean rememberMe, HttpServletResponse response) { // 验证用户名和密码 // ... // 生成Remember-me cookie if (rememberMe) { TokenBasedRememberMeServices rememberMeServices = new TokenBasedRememberMeServices("remember-me-key", userDetailsService); rememberMeServices.setTokenValiditySeconds(86400); rememberMeServices.setAlwaysRemember(true); rememberMeServices.loginSuccess(request, response, authentication); } // ... } ``` 其中,如果用户勾选了Remember-me复选框,则调用TokenBasedRememberMeServices的loginSuccess方法生成Remember-me cookie。 4. 在下次访问时验证Remember-me cookie,例如: ``` http .csrf().disable() .authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .antMatchers("/user/**").hasAnyRole("USER", "ADMIN") .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .and() .rememberMe() .key("remember-me-key") .rememberMeParameter("remember-me") .tokenValiditySeconds(86400) .userDetailsService(userDetailsService); ``` 其中,Remember-me cookie会在每次请求时被自动验证,如果验证通过,则用户会被认为已经登录。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值