Spring安全性共享多个线程之间的上下文,我该如何避免这种情况?

时间:2016-06-27 23:02:36

标签: spring spring-security jwt

我一直致力于基于Spring的服务,使用JWT进行身份验证。

处理用户请求的服务在过滤器中调用授权服务,该过滤器设置安全上下文,看起来非常像这样:

@Component
public class TokenAuthenticationFilter extends OncePerRequestFilter {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private AuthorizationServiceClient authorizationServiceClient;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
            User user = authorizationServiceClient.requestUserFromToken(request.getHeader("X-Auth-Token"));
            SecurityContextHolder.getContext().setAuthentication(new UserAuthentication(user));
            filterChain.doFilter(request, response);
            SecurityContextHolder.getContext().setAuthentication(null);
        } catch (HttpClientErrorException e) {
            response.sendError(e.getStatusCode().value());
        }
    }
}

AuthorizationServiceClient调用远程服务,该服务处理用户角色和凭据的验证。

我一直面临着一种非常奇怪的行为:

当我的UI上的某个页面同时发出多个请求时,我最终得到一个500,由NullPointerException引起。

根本原因是Principal(包含用户的身份)为null,当它不应该有。

1 个答案:

答案 0 :(得分:1)

经过一次痛苦的调查后,我结束了,确认SecurityContextHolder,即使它使用的是ThreadLocal,也在使用会话,然后在线程之间共享。

SecurityContextHolder.getContext().setAuthentication(null);在同一会话中发出某些请求并且正在导致NPE时,http. [...] .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS). [...] 正在删除并发线程中使用的值。

所以,如果像我一样,你想阻止使用会话,你需要使用以下方式设置安全性:

CREATE OR REPLACE TRIGGER TRG_LINE_PRODUCT AFTER INSERT UPDATE OR DELETE ON 
TBL_CH08_LINE FOR EACH ROW
BEGIN
IF INSERTING THEN UPDATE TBL_CH08_PRODUCT P SET P_QOH = P_QOH-:NEW.LINE.UNITS
WHERE P.P_CODE = :NEW.P.P_CODE;
END IF;
END;
/