项目需要,要求登录用户非空闲状态,不可退出。说白了就是,在退出的时候增加逻辑判断,如果状态为非空,就不让其退出。
仔细查看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;
}
}
问题搞定!