描述

在使用shiro的时候,经常会有一种需求: 把登录成功后的用户对象存放到session中,方面其他地方调用。存放到session这个步骤到底应该在哪里去做,有几个地方比较合适:

  • 调用Subject.login() 的时候
  • 使用cas进行单点认证的时候,集成CasFilter重写onLoginSuccess()方法
  • 实现AuthenticationListener接口,实现onSuccess接口

以上三种方法,都可以做到登录成功以后把用户对象存放到session中,但是都没有考虑到一点,使用保存登录(Remembere)进行自动登录的情况,以上的几个方法都不会被调用,也没有找到onRemembereLogin类似的接口。

解决方案

在需要用户登录权限的地方添加一个过滤器: 判断如果用户是登录状态,并且session里的用户对象为空,则去数据库中查询用户对象放入session中。
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

public class UserSessionFilter extends AccessControlFilter {
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
Subject subject = getSubject(request, response);
if (subject == null) {
// 没有登录
return false;
}
HttpSession session = WebUtils.toHttp(request).getSession();
Object sessionUsername = session.getAttribute(GlobalConstant.SESSION_AUTH_LOGIN_USERNAME);
if (sessionUsername == null) {
// 你自己的逻辑
}
return true;
}

@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
return true;
}

@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
return true;
}
}

spring配置:

1
2
3
4
5
6
7
8
9
<bean id="userSessionFilter" class="com.chinamedcom.his.common.auth.UserSessionFilter"/>
<!-- 在ShiroFilterFactoryBean的filters中加入 -->
<property name="filters">
<util:map>
<entry key="userSession" value-ref="userSessionFilter"/>
<!-- ..... -->
<!-- 你的其他filter -->
</util:map>
</property>

filterChainDefinitions中加上:

1
/** = user,userSession