我们经常在登陆网站时看到一个选项,就是 记住我、 n天内自动登陆。本章我们使用 Shiro 来实现这个功能。
首先需要在 spring-shiro.xml
中配置:
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager"> <property name="cookie" ref="cookie"/> </bean>
<bean id="cookie" class="org.apache.shiro.web.servlet.SimpleCookie">
<!-- cookie 名称 -->
<property name="name" value="rememberMe"/>
<!-- cookie 过期时间 -->
<property name="maxAge" value="86400"/>
</bean>
并将 rememberMeManager
添加到 securityManager
中:
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
<property name="rememberMeManager" ref="rememberMeManager"/>
</bean>
在之前的章节中我们提到了过滤器链中的 user
过滤器,以及注解中的 @RequiresUser
都是用来表示已登陆或 rememberMe
状态可访问。
我们新建一个页面 remember.jsp
,并为其配置 user
过滤器:
remember.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>记住我</title>
</head>
<body>
RememberMe Page
</body>
</html>
过滤器
/remember.jsp = user
当然,还要通过表单的单选框来告诉 Shiro,当前用户是否使用 rememberMe
功能,修改后的login.jsp
:
<html>
<body>
<form action="login" method="post">
username : <input type="text" name="username">
<br>
password : <input type="password" name="password">
<br>
rememberMe: <input type="checkbox" name="rememberMe">
<br>
<input type="submit" value="Login">
</form>
</body>
</html>
并在 Controller 层接受后,将复选框选中结果配置给 Shiro:
@RequestMapping("login")
@ResponseBody
public String login(User user) {
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token =
new UsernamePasswordToken(user.getUsername(), user.getPassword(), user.getRememberMe());
try {
subject.login(token);
} catch (AuthenticationException e) {
return e.getMessage();
}
return "login success";
}
一切配置完成后启动项目,登陆时勾选 rememberMe
,然后关闭浏览器,重新打开,再访问 remember.jsp
看是否可以访问,并对比其他配置 authc 或需要授权的页面,是否可以访问。
其实他的原理就是通过 cookie 实现,勾选 remberMe
后登陆成功会给浏览器设置一个 cookie,以及其到期时间,请求页面时验证该 cookie 的内容是否是服务器颁发的,如果是则通过,不是则跳回登陆页面。
也可能你配置了 rememberMe
功能但未生效,也没有报错,那么可能是以下两种原因。
- 检查浏览器是否禁用了 Cookie
- 检查是否使用了注解
@RequiresUser
并同时在过滤器链中配置了/** = authc
,原因是过滤器链的优先级高于@RequiresUser
,在/** = authc
时,表示所有请求都要认证,所以还没有到注解的验证就已经被拦截并跳回到登陆页面了。
不过 rememberMe
功能要慎用,且过期时间不要设置太久,因为这样即使修改密码后,原先的 cookie 在过期之前还是可以使用的。还有一个问题是,rememberMe
状态下无法获取用户的 Session 信息,从而也会引发其他的问题。
本章代码地址 : https://github.com/zhaojun1998/Premission-Study/tree/master/Permission-Shiro-11/