【问题标题】:spring security with jwt token returns 401 html page not json带有jwt令牌的spring security返回401 html页面而不是json
【发布时间】:2021-07-24 11:10:35
【问题描述】:

为什么 spring 返回 401 html 页面而不是我的自定义 json api 响应错误?以及修复它的最佳方法是什么(覆盖弹簧配置)

安全性:

@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .httpBasic().disable()
            .csrf().disable()
            .cors().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
            .authorizeRequests()
            .antMatchers("/v2/api-docs").permitAll()
            .antMatchers("/configuration/ui").permitAll()
            .antMatchers("/swagger-resources/**").permitAll()
            .antMatchers("/configuration/security").permitAll()
            .antMatchers("/swagger-ui.html").permitAll()
            .antMatchers("/swagger-ui/*").permitAll()
            .antMatchers("/webjars/**").permitAll()
            .antMatchers("/v2/**").permitAll()
            .antMatchers(LOGIN_ENDPOINT, REGISTER_ENDPOINT, "/v2/api-docs", "/swagger-ui.html", 
"/v2/swagger-ui.html").permitAll()
            .antMatchers(ADMIN_ENDPOINT).hasRole("ADMIN")
            .anyRequest().authenticated()
            .and()
            .apply(new JwtConfigurer(jwtTokenProvider));
}

过滤器:

public class JwtTokenFilter extends GenericFilterBean {
private final JwtTokenProvider jwtTokenProvider;

public JwtTokenFilter(JwtTokenProvider jwtTokenProvider) {
    this.jwtTokenProvider = jwtTokenProvider;
}

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain)
        throws IOException, ServletException {

    String token = jwtTokenProvider.resolveToken((HttpServletRequest) req);

    try {
        if (token != null && jwtTokenProvider.isTokenValid(token)) {
            var authentication = jwtTokenProvider.getAuthentication(token);

            if (authentication != null) {
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
    } catch (JwtAuthenticationException e) {
        SecurityContextHolder.clearContext();
        ((HttpServletResponse) res).sendError(e.getHttpStatus().value());
        ((HttpServletResponse) res).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        filterChain.doFilter(req, res);
        throw new JwtAuthenticationException("JWT token is expired or invalid", 
HttpStatus.UNAUTHORIZED);
    }
    filterChain.doFilter(req, res);
}
}

所以我实现了自定义异常处理程序和过滤器,我需要的是这种类型的错误

{
   "errorMessage": "Invalid username or password",
   "validationErrors": null
}

我在登录 fo 示例时得到的,获取令牌的成功案例也在工作

{
"username": "vovaflex",
"token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ2b3ZhZmxleCIsInJvbGVzIjpbIlJPTEVfVVNFUiJdLCJpYXQiOjE2MTk4NjQ2MDksImV4cCI6MTYxOTg2ODIwOX0.Oc7AG5ZncfAT3QB8l0mkYDkBr5ZjBfJ2MxLe3M12DF8",
"roles": [
    {
        "id": 1,
        "created": "2021-04-03T18:14:51.891+00:00",
        "updated": "2021-04-03T18:14:51.891+00:00",
        "status": "ACTIVE",
        "name": "ROLE_USER",
        "users": null
    }
]
}

但是,例如令牌不正确或过期,我得到 401 未经授权(正确),但不是带有我设置的消息的 json,而是得到带有错误的完整 html 页面

<!doctype html>
<html lang="en">
<head>
    <title>HTTP Status 401 – Unauthorized</title>
</head>

<body>
    <h1>HTTP Status 401 – Unauthorized</h1>
</body>
</html>

【问题讨论】:

    标签: java spring spring-security jwt


    【解决方案1】:

    对于自定义 JSON 错误块,你需要做两件事

    1. 实现 AuthenticationEntryPoint

      公共类 AuthExceptionEntryPoint 实现 AuthenticationEntryPoint { @覆盖 公共无效开始(HttpServletRequest 请求,HttpServletResponse 响应,AuthenticationException arg2)抛出 IOException,ServletException {

       }
      

      }

    并在网络安全设置配置(HttpSecurity http)中添加该引用

    @Configuration
    @EnableResourceServer
    public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter
    {   
        @Override
        public void configure(HttpSecurity http) throws Exception
        {
            http.exceptionHandling().authenticationEntryPoint(new AuthExceptionEntryPoint()) ;
    
        }
    }
    

    查看这两个资源了解更多详情

    JSON custom authentication

    JSON custom error response

    【讨论】:

    • 我可以使用“http.exceptionHandling().authenticationEntryPoint(new AuthExceptionEntryPoint());”来自我的 WebSecurityConfigurerAdapter ?
    猜你喜欢
    • 2018-11-06
    • 2020-11-04
    • 2018-09-21
    • 2021-12-03
    • 2016-03-22
    • 2018-08-27
    • 2021-07-28
    • 2018-12-07
    • 2017-03-21
    相关资源
    最近更新 更多