项目需要,要求登录用户非空闲状态,不可退出。说白了就是,在退出的时候增加逻辑判断,如果状态为非空,就不让其退出。
仔细查看spring security文档,发现这个框架里维护了一个过滤器链,来提供服务。而我退出策略用的是LogoutFilter,框架默认提供的过滤器。代码如下:
<sec:http use-expressions="false" auto-config="true" entry-point-ref="loginUrlAuthenticationEntryPoint"> <sec:intercept-url pattern='/**' access='ROLE_LOGIN' /> **<sec:logout invalidate-session="true" logout-url="/logout" success-handler-ref="logoutSuccessHandler" delete-cookies="JSESSIONID"/>** <sec:csrf disabled="true" /> <sec:custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" /> <sec:custom-filter before="FORM_LOGIN_FILTER" ref="authFilter" /> <sec:session-management invalid-session-url="/sessionexpired" session-authentication-strategy-ref="sas" /> </sec:http>
而框架提供过滤器链如下:
因此可以自定义过滤器,赶在LogoutFilter之前执行,配置如下:
<sec:custom-filter before="LOGOUT_FILTER" ref="cloudqLogoutFilter" /> <bean id="cloudqLogoutFilter" class="com.raymon.cloudq.security.CloudqLogoutFilter"> <property name="logoutUrl" value="/logout" /> </bean>
filter代码如下
/** * 非空闲状态下,用户不能退出 * Created by on 2017/11/7. */ public class CloudqLogoutFilter extends GenericFilterBean { private org.slf4j.Logger logger = LoggerFactory.getLogger(getClass()); private ObjectMapper mapper = new ObjectMapper(); private String logoutUrl; @Autowired WindowCurrentStateMapper windowCurrentStateMapper @Override protected void initFilterBean() throws ServletException { super.initFilterBean(); mapper.setPropertyNamingStrategy(new PropertyNamingStrategy.UpperCamelCaseStrategy()); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; if (this.requiresLogout(request, response) && SecurityContextHolder.getContext() != null && SecurityContextHolder.getContext().getAuthentication() != null) { AuthUserDetails authUser = (AuthUserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); ClientEmp clientEmp = authUser.getClientEmpUser(); Integer empId = clientEmp.getEmpId(); Integer branchesId = clientEmp.getBranchesId(); List<WindowsParticulars> windowEmpList = windowCurrentStateMapper.selectbyEmpId(branchesId, empId); if (windowEmpList != null && windowEmpList.size() > 0) { for (WindowsParticulars windowEmp : windowEmpList) { if (Constants.WINDOW_CURRENT_STATE_CALL.equals(windowEmp.getCurrentState()) || Constants.WINDOW_CURRENT_STATE_IN_PROCESS.equals(windowEmp.getCurrentState())) { logger.info("您的账号id='{}',name='{}',非空闲状态下,用户不能退出", clientEmp.getEmpId(), clientEmp.getEmpName()); printErrorMsg(servletResponse); return; } } } } filterChain.doFilter(servletRequest, servletResponse); } private void printErrorMsg(ServletResponse servletResponse) { servletResponse.setContentType("application/json"); servletResponse.setCharacterEncoding("UTF-8"); PrintWriter out = null; try { out = servletResponse.getWriter(); Result result = new Result(StatusCode.ERROR_WINDOW_NOT_HANDLE, null, "非空闲状态下,用户不能退出"); out.write(mapper.writeValueAsString(result)); } catch (IOException e) { e.printStackTrace(); } finally { if (out != null) { out.close(); } } } /** * 判断请求路径是否是退出 * * @param request * @param response * @return */ private boolean requiresLogout(HttpServletRequest request, HttpServletResponse response) { if (StringUtils.isBlank(logoutUrl)) return false; String path = request.getRequestURI(); return path.contains(logoutUrl); } public void setLogoutUrl(String logoutUrl) { this.logoutUrl = logoutUrl; } }
问题搞定!