Spring Security Session会话管理

611 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

设置session过期时间和自定义处理

1.配置文件

server:
  servlet:
    session:
      # session 会话超时时间:>60s,带单位:s,m,h,d
      timeout: 1m

2.spring security设置过期策略

2.1实现==InvalidSessionStrategy==接口

/**
 * session过期处理
 *
 * @author zhong
 */
public class MyInvalidSessionStrategy implements InvalidSessionStrategy {


    @Override
    public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        // 清除Cooke
        cancelCookie(request, response);
        // 返回信息
        Map<String, Object> result = new HashMap<>(10);
        result.put("msg", "session过期!");
        response.setContentType("application/json;charset=UTF-8");
        ObjectMapper mapper = new ObjectMapper();
        response.getWriter().write(mapper.writeValueAsString(result));
    }

    void cancelCookie(HttpServletRequest request, HttpServletResponse response) {
        Cookie cookie = new Cookie("JSESSIONID", null);
        cookie.setMaxAge(0);
        cookie.setPath(getCookiePath(request));
        response.addCookie(cookie);
    }

    String getCookiePath(HttpServletRequest request) {
        String contextPath = request.getContextPath();
        return (contextPath.length() > 0) ? contextPath : "/";
    }
}

2.2 将自定义的失效处理添加到框架中

@Resource
private InvalidSessionStrategy invalidSessionStrategy;
@Override
protected void configure(HttpSecurity http) throws Exception {
//session管理

http.sessionManagement()
    	// 设置无效处理
        .invalidSessionStrategy(invalidSessionStrategy);
}

限制用户登陆设备个数实现

1.实现==SessionInformationExpiredStrategy==接口

/**
 * 多用户session管理
 *
 * @author zhong
 */
public class CustomSessionInformationExpiredStrategy implements SessionInformationExpiredStrategy {
    private CustomAuthenticationFailureHandler failureHandler;

    public void setFailureHandler(CustomAuthenticationFailureHandler failureHandler) {
        this.failureHandler = failureHandler;
    }

    @Override
    public void onExpiredSessionDetected(SessionInformationExpiredEvent event) {
        try {
            User user = (User) event.getSessionInformation().getPrincipal();
            AuthenticationException ep = new AuthenticationServiceException(String.format("用户【%s】在多台设备登陆", user.getUsername()));
            failureHandler.onAuthenticationFailure(event.getRequest(), event.getResponse(), ep);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

2.将SessionInformationExpiredStrategy添加容器中

@Resource
private CustomAuthenticationFailureHandler failureHandler;

@Bean
@ConditionalOnMissingBean(SessionInformationExpiredStrategy.class)
public SessionInformationExpiredStrategy sessionInformationExpiredStrategy() {
    CustomSessionInformationExpiredStrategy strategy = new CustomSessionInformationExpiredStrategy();
    // 注入失败处理类
    strategy.setFailureHandler(failureHandler);
    return strategy;
}

3.设置过期策略

@Override
protected void configure(HttpSecurity http) throws Exception {
    //session管理
    http
            .sessionManagement()
            // 设置无效处理
            .invalidSessionStrategy(invalidSessionStrategy)
            // 设置最大session数(登陆数)
            .maximumSessions(1)
            //超过最大session数策略
            .expiredSessionStrategy(sessionInformationExpiredStrategy)
    ;

}