在shiro的登录中,可以设置rememberMe作为记住我的功能
<bean id="formAuthenticationFilter"
class="cn.echo.web.shiro.MyFormAuthenticationFilter">
<property name="usernameParam" value="username" />
<property name="passwordParam" value="password" />
<property name="rememberMeParam" value="rememberMe"/>
<property name="loginUrl" value="/user/login.do" />
bean>
但是shiro自带的记住我功能,在用户登录时,并不会把登录的用户的principal放到session中
在非记住我登录时,则会将principal放入session中
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
//用户帐号
String username = (String) token.getPrincipal();
System.out.println(token.getCredentials());
// 根据用户帐号从数据库取出盐和加密后的值
// 如果根据账号没有找到用户信息则返回null,shiro抛出异常"账号不存在"
User user = userService.selectByPrimaryKey(username);
if(user == null) {
throw new UnknownAccountException("帐号不存在");
} else if(user.getActiState().equals(0)) {
throw new UnknownAccountException("用户未激活!请重新注册!");
}
String password = user.getUserPassword();
String salt = user.getSalt();
ActiveUser activeUser = new ActiveUser();
activeUser.setUserId(username);
activeUser.setUserNickname(user.getUserNickname());
activeUser.setUserEmail(user.getUserEmail());
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(activeUser, password, ByteSource.Util.bytes(salt), this.getName());
return authenticationInfo;
}
其中的activeUser就是principal,在返回后,shiro会将该activeUser添在session中,而在rememberMe时并不会将该principal添加,这样会导致前端获取不到session的user
解决方法:
实现HandlerInterceptor中的preHandle()方法
截取登录时的subject,判断是否是通过rememberMe登录,将principal手动添加到session中
package cn.echo.web.shiro;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import cn.echo.web.pojo.ActiveUser;
import cn.echo.web.pojo.User;
import cn.echo.web.service.UserService;
/**
* 拦截rememberMe的请求,添加user到session中
* @author echo
*
*/
public class RememberMeInterceptor implements HandlerInterceptor {
private final Logger logger = Logger.getLogger(RememberMeInterceptor.class);
@Autowired
private UserService userService;
public RememberMeInterceptor() {
// TODO Auto-generated constructor stub
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 获取session中的subject
Subject user = SecurityUtils.getSubject();
// 判断是不是通过记住我登录
if( !user.isAuthenticated() && user.isRemembered()) {
logger.debug("remembered me, put user in session");
user.getSession().setAttribute("user", user.getPrincipal());
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
}
}