当前位置: 首页 > 知识库问答 >
问题:

Spring security BasicAuthenticFilter返回403而不是401

华英睿
2023-03-14

我已经实现了JWT认证和授权。一切都很好,除了未经授权的场景

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

结果:禁止403例,未批准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;
    } 

以下是我的完整课程:

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());

共有1个答案

薛烨霖
2023-03-14

如果查看使用JWTAuthorizationFilter重写的BasicAuthenticationFilter在身份验证失败时执行的操作,它将调用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.getreasonprach());
 类似资料:
  • 我试图让2支球队互相比赛。当我说团队1.玩(团队2)时,我称之为;当 i 生成的数字小于 0.5 时,team2 应获胜,如果大于 0.5,则团队 1 应获胜。当团队 1 获胜时,它会正确显示为尼克斯,但当团队 2 获胜时,它会显示内存地址。我怎么能让它正确地说网是赢的,而不是team@78987neu73

  • 问题内容: 这是我的发件人实体 当我尝试执行以下查询时: 发生以下错误: 错误:org.hibernate.property.BasicPropertyAccessor- HHH000123:类中的IllegalArgumentException:be.gimme.persistence.entities.Sender,属性的设置方法:senderId 错误:org.hibernate.prope

  • 我正在使用Yaml(和Python!)第一次。我试图从一个.yaml文件中加载多个文档,但没有得到我所期望的结果。我正在期待一个包含每个文档的dicts的dict返回,但却得到了一个生成器对象...?我应该注意到,当我在前面的测试中对单个文档yaml文件使用yaml.load()(而不是load_all())时,我能够很好地取回一个字典。 ...产生以下终端输出:

  • 我写了自己的类加载器,它与类一起工作,实现了接口插件。但是我不能将类转换为插件。怎么了? 错误:(18,47)java:不兼容的类型:java。lang.类无法转换为插件 我补充说,这是我的SimpleClassLoader类的主要部分,它扩展了ClassLoader。

  • await返回[Function]而不是value 尝试使用async和await函数从firebase返回查询的值。返回的结果是[Function]或未处理的承诺拒绝警告。async和await是新的承诺,但我在几个网站上尝试了基本的示例,大多数都有resolve和reject参数,我认为这应该与firebase的承诺相同。 我试了两个不同版本,结果都不正确。 返回UnhandledPromis

  • 代码段用于获取从文本文件中提取的一行文本,将其分离为单独的标记,并将每个标记存储在数组的索引中。起初我以为问题出在文本文件上,但是直接将字符串放入编辑器并不能解决这个问题。 使用字符串,如: 带分隔符的StringTokenizer对象返回前四个标记作为正确的字符串,但其余四个标记为null。 有趣的是,另一个字符串: “Gnollnonegeralany222taunttaunt” 鸡肉没有野兽