Spring Security BasicAuthenticationFilter返回403而不是401

时间:2020-06-24 19:24:35

标签: spring spring-security

我已经实现了JWT身份验证和授权。除了未经授权的情况之外,一切都正常运行

未经授权的情况:对路由进行http调用而未提供授权令牌。

结果:禁止403,而不是未经授权

这是我的代码:

@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
    String header = req.getHeader(HEADER_STRING);

    if (header == null || !header.startsWith(TOKEN_PREFIX)) {
        chain.doFilter(req, res);
        return;
    }

    UsernamePasswordAuthenticationToken authentication = getAuthentication(req);

    SecurityContextHolder.getContext().setAuthentication(authentication);
    chain.doFilter(req, res);
}

之后

    if (header == null || !header.startsWith(TOKEN_PREFIX)) {
        chain.doFilter(req, res);
        return;
    } 

执行,响应为403

这是我的全部课程:

public class JWTAuthorizationFilter extends BasicAuthenticationFilter {

    public JWTAuthorizationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
        String header = req.getHeader(HEADER_STRING);

        if (header == null || !header.startsWith(TOKEN_PREFIX)) {
            chain.doFilter(req, res);
            return;
        }

        UsernamePasswordAuthenticationToken authentication = getAuthentication(req);

        SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(req, res);
    }

    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {

        String token = request.getHeader(HEADER_STRING);
        if (token != null) {

            // setting the user in the security context
            String user = JWT.require(Algorithm.HMAC512(SECRET.getBytes()))
                    .build()
                    .verify(token.replace(TOKEN_PREFIX, ""))
                    .getSubject();

            if(user != null){
                return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
            }

            return null;
        }

        return null;
    }
}

备注

我在 UsernamePasswordAuthenticationFilter 上遇到了同样的问题,我通过覆盖默认的authenticationFailureHandler来解决了这个问题:

setAuthenticationFailureHandler(new JWTAuthenticationFailureHandler());

如何获取正确的401响应代码和正文?

谢谢!

1 个答案:

答案 0 :(得分:2)

如果您查看认证失败时要用BasicAuthenticationFilter覆盖的JWTAuthorizationFilter会做什么,它将调用authenticationEntryPoint.commence(request, response, failed)并发送401

BasicAuthenticationEntryPoint

    public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authException) throws IOException {
        response.addHeader("WWW-Authenticate", "Basic realm=\"" + realmName + "\"");
        response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
    }

但是您有被覆盖并返回null的行为。因此,请尝试以下操作之一:

  • BadCredentialsException放回您要返回null的位置
  • 执行response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());