Spring security BasicAuthenticationFilter返回403而不是401

Spring security BasicAuthenticationFilter返回403而不是401,spring,spring-security,Spring,Spring Security,我已经实现了JWT身份验证和授权。除了未经授权的情况外,一切正常 未经授权的场景:在不提供授权令牌的情况下对路由进行http调用 结果:403禁止而非未经授权 这是我的密码: @Override protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException { String he

我已经实现了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;
    }
}
如何获得正确的401响应代码和正文


谢谢

如果查看在身份验证失败时使用JWTAuthorizationFilter覆盖的
BasicAuthenticationFilter
基本身份验证筛选器所做的操作,它将调用
authenticationEntryPoint.Start(请求、响应、失败)
,发送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的行为。因此,请尝试以下方法之一:

  • 在返回null的位置抛出
    BadCredentialsException
  • Do
    response.sendError(HttpStatus.UNAUTHORIZED.value(),HttpStatus.UNAUTHORIZED.getReasonPhrase())

第二种解决方案(res.sendError())应该可以工作,但我会尝试寻找另一种解决方案,因为我在很多地方都必须这样做,而且太过手动。抛出BadCredentialsException无效。明天我将查看authenticationEntryPoint。我想如果我将它传递给构造函数,应该调用comment方法,你能给我一个提示吗?提供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());
    }