《跟我学Shiro》笔记24-在线会话管理

  1. 会话控制器
  2. ForceLogoutFilter
  3. 登录控制器
  4. spring-config-shiro.xml

原文地址:第二十四章 在线会话管理——《跟我学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" 转载请保留原文链接及作者。

目录