《跟我学Shiro》笔记24-在线会话管理
原文地址:第二十四章 在线会话管理——《跟我学Shiro》
目录贴: 跟我学Shiro目录贴
有时候需要显示当前在线人数、当前在线用户,有时候可能需要强制某个用户下线等;此时就需要获取相应的在线用户并进行一些操作。
会话控制器
@RequiresPermissions("session:*")
@Controller
@RequestMapping("/sessions")
public class SessionController {
@Autowired
private SessionDAO sessionDAO;
// 提供了展示所有在线会话列表,通过sessionDAO.getActiveSessions()获取所有在线的会话。
@RequestMapping()
public String list(Model model) {
Collection<Session> sessions = sessionDAO.getActiveSessions();
model.addAttribute("sessions", sessions);
model.addAttribute("sessionCount", sessions.size());
return "sessions/list";
}
// 强制退出某一个会话,此处只在指定会话中设置
@RequestMapping("/{sessionId}/forceLogout")
public String forceLogout(
@PathVariable("sessionId") String sessionId, RedirectAttributes redirectAttributes) {
try {
Session session = sessionDAO.readSession(sessionId);
if(session != null) {
session.setAttribute(Constants.SESSION_FORCE_LOGOUT_KEY, Boolean.TRUE);
}
} catch (Exception e) {/*ignore*/}
redirectAttributes.addFlashAttribute("msg", "强制退出成功!");
return "redirect:/sessions";
}
}
Constants.SESSION_FORCE_LOGOUT_KEY
属性,之后通过 ForceLogoutFilter
判断并进行强制退出。
ForceLogoutFilter
public class ForceLogoutFilter extends AccessControlFilter {
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
Session session = getSubject(request, response).getSession(false);
if(session == null) {
return true;
}
return session.getAttribute(Constants.SESSION_FORCE_LOGOUT_KEY) == null;
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
try {
getSubject(request, response).logout();//强制退出
} catch (Exception e) {/*ignore exception*/}
String loginUrl = getLoginUrl() + (getLoginUrl().contains("?") ? "&" : "?") + "forceLogout=1";
WebUtils.issueRedirect(request, response, loginUrl);
return false;
}
}
强制退出拦截器,如果用户会话中存在 Constants.SESSION_FORCE_LOGOUT_KEY 属性,表示被管理员强制退出了;然后调用 Subject.logout() 退出,且重定向到登录页面(自动拼上 fourceLogout 请求参数)。
登录控制器
@Controller
public class LoginController {
@RequestMapping(value = "/login")
public String showLoginForm(HttpServletRequest req, Model model) {
String exceptionClassName = (String)req.getAttribute("shiroLoginFailure");
String error = null;
if(UnknownAccountException.class.getName().equals(exceptionClassName)) {
error = "用户名/密码错误";
} else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
error = "用户名/密码错误";
} else if(exceptionClassName != null) {
error = "其他错误:" + exceptionClassName;
}
model.addAttribute("error", error);
if(req.getParameter("forceLogout") != null) {
model.addAttribute("error", "您已经被管理员强制退出,请重新登录");
}
return "login";
}
}
spring-config-shiro.xml
和之前的唯一区别是在 shiroFilter 中的 filterChainDefinitions 拦截器链定义中添加了 forceLogout 拦截器:
<bean id="sysUserFilter" class="com.github.zhangkaitao.shiro.chapter24.web.shiro.filter.SysUserFilter"/>
<bean id="forceLogoutFilter" class="com.github.zhangkaitao.shiro.chapter24.web.shiro.filter.ForceLogoutFilter"/>
<!-- Shiro的Web过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login"/>
<property name="filters">
<util:map>
<entry key="authc" value-ref="formAuthenticationFilter"/>
<entry key="sysUser" value-ref="sysUserFilter"/>
<entry key="forceLogout" value-ref="forceLogoutFilter"/>
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
/login = authc
/logout = logout
/authenticated = authc
/** = forceLogout,user,sysUser
</value>
</property>
</bean>
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 bin07280@qq.com
文章标题:《跟我学Shiro》笔记24-在线会话管理
文章字数:707
本文作者:Bin
发布时间:2018-04-28, 20:12:22
最后更新:2019-08-06, 00:42:19
原始链接:http://coolview.github.io/2018/04/28/%E8%B7%9F%E6%88%91%E5%AD%A6Shiro/%E3%80%8A%E8%B7%9F%E6%88%91%E5%AD%A6Shiro%E3%80%8B%E7%AC%94%E8%AE%B024-%E5%9C%A8%E7%BA%BF%E4%BC%9A%E8%AF%9D%E7%AE%A1%E7%90%86/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。