尽管身份验证完成,为啥 SpringBoot Security 不向 REST 客户端返回任何响应

Posted

技术标签:

【中文标题】尽管身份验证完成,为啥 SpringBoot Security 不向 REST 客户端返回任何响应【英文标题】:Why doesn't SpringBoot Security return any response to REST client although the authentication is done尽管身份验证完成,为什么 SpringBoot Security 不向 REST 客户端返回任何响应 【发布时间】:2020-03-06 15:15:54 【问题描述】:

我正在尝试在 SpringBoot 中使用 REST API 实现 JWT 身份验证。当我调试我的代码时,我看到 JWT Authenticator 工作正常,但我看不到 Spring Security 框架调用了 JWT 授权代码,并且没有响应发送到我的 REST 客户端。以下是我认为与我的问题有关的代码的一些部分。

我认为我的请求在 Spring Security 流程中的某个地方丢失了......

WebSecurityConfig:

@EnableWebSecurity(debug = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 

      @Override
      protected void configure(HttpSecurity http) throws Exception 
        http.cors()
            .and()
            .csrf()
            .disable()
            .authorizeRequests()
            .antMatchers("/admin/**")
            .hasRole("ADMIN")
            .anyRequest()
            .authenticated()
            .and()
            .addFilter(new JWTAuthenticationFilter(authenticationManager()))
            .addFilter(new JWTAuthorizationFilter(authenticationManager()))
            // this disables session creation on Spring Security
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
      

JWTAuthenticationFilter:

public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter 


  public JWTAuthenticationFilter(AuthenticationManager authenticationManager) 
    setAuthenticationManager(authenticationManager);
  

  @Override
  public Authentication attemptAuthentication(HttpServletRequest request,
      HttpServletResponse response) throws AuthenticationException 
    if (!HttpMethod.POST.matches(request.getMethod())) 
      throw new AuthenticationServiceException(
          "Authentication method not supported: " + request.getMethod());
    

    try 
      JsonAuthenticationParser auth =
          new ObjectMapper().readValue(request.getInputStream(), JsonAuthenticationParser.class);
      System.out.println(auth.username);
      System.out.println(auth.password);
      UsernamePasswordAuthenticationToken authRequest =
          new UsernamePasswordAuthenticationToken(auth.username, auth.password);

      return this.getAuthenticationManager().authenticate(authRequest);
     catch (Exception e) 
      log.warn("Auth failed!!!!!!!!!!!!");
      throw new InternalAuthenticationServiceException("Could not parse authentication payload");
    
  

  @Override
  protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res,
      FilterChain chain, Authentication auth) throws IOException, ServletException 

    String token = Jwts.builder().setSubject(((User) auth.getPrincipal()).getUsername())
        .claim("roles", ((User) auth.getPrincipal()).getAuthorities())
        .setExpiration(new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME))
        .signWith(SignatureAlgorithm.HS512, SecurityConstants.SECRET.getBytes()).compact();
    res.addHeader(SecurityConstants.HEADER_STRING, SecurityConstants.TOKEN_PREFIX + token);
    System.out.println("Token:"+token);
  

JWTAuthorizationFilter

public class JWTAuthorizationFilter extends BasicAuthenticationFilter 

  public JWTAuthorizationFilter(AuthenticationManager authManager) 
    super(authManager);
  

  @Override
  protected void doFilterInternal(
      HttpServletRequest req, HttpServletResponse res, FilterChain chain)
      throws IOException, ServletException 
    System.out.println("++++++++++++++++++++++++++++AUTHERIZATION doFilterInternal++++++++++++++++++++++");

  

  private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) 
    System.out.println("++++++++++++++++++++++++++++AUTHERIZATION getAuthentication++++++++++++++++++++++");

  

【问题讨论】:

【参考方案1】:

背景

当您将过滤器添加到过滤器链而不指定顺序 (http.addFilter(...)) 时,比较器 HttpSecurity 用于确定其在链中的顺序会查看过滤器的父类。 UsernamePasswordAuthenticationFilter 位于 BasicAuthenticationFilter 之前(参见 FilterComparator)。

请求进来,到达JWTAuthenticationFilter,并在successfulAuthentication()方法中“结束”。

解决方案

继续JWTAuthenticationFilter中的过滤器链:

@Override
protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res,
                                FilterChain chain, Authentication auth) 
                                   throws IOException, ServletException 

    // ...

    chain.doFilter(req, res);


【讨论】:

谢谢,调用chain.doFilter方法后,SpringBoot调用了JWTAuthorizationFilter,但它返回了禁止(http 403)给我的客户端... 您是否为具有 ADMIN 角色的用户使用凭据(因为这是您在配置中指定的)?

以上是关于尽管身份验证完成,为啥 SpringBoot Security 不向 REST 客户端返回任何响应的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Spring Security 身份验证会导致 CORS 错误

LDAP 身份验证超时

请问我的华为手机为啥不能进行谷歌身份验证(已生成验证码但不能用)?

LDAP:在身份验证事件期间获取自定义值

为啥 IIS 10 服务器在 Office 365 用户身份验证后显示 localhost

Django-为啥内置身份验证登录功能在成功登录网址后未将有关用户的信息传递给