JWT 认证成功,但是邮递员返回 404

Posted

技术标签:

【中文标题】JWT 认证成功,但是邮递员返回 404【英文标题】:JWT authenticated succesfully, but the postman return 404 【发布时间】:2020-11-17 03:45:06 【问题描述】:

所以,这是我第一次使用 jwt 作为我的 API 的身份验证,我从其他来源看到了很多示例,最后我写进了我的代码,如下所示。 (请不要介意那里未使用的变量)。

我的目标是使用从登录阶段生成的 jwt 与我的 sso 对来自 /engagement/** 端点的任何请求进行身份验证,然后解码该 jwt 并在点击参与 API 时对其进行验证,直到此时,当我看到我的日志时,当我点击我的参与 API 时,任何身份验证都运行顺利。

但是,最后,不是返回我的 json 数据(是的,我的数据库中有参与数据),邮递员总是给我错误 404,我不知道为什么。 这有什么问题?

AuthenticationFilter.java

public class AuthenticationFilter extends AbstractAuthenticationProcessingFilter 

    @Value("$fintax.app.client_secret")
    private String clientSecret;
    
    private static final Logger logger = LoggerFactory.getLogger(AuthenticationFilter.class);
    private final ObjectMapper objectMapper = new ObjectMapper();
    private static final String ERROR_MESSAGE = "Something went wrong while parsing /login request body";
    private AuthenticationManager authManager;
    
    AuthenticationFilter(final RequestMatcher requiresAuth) 
        super(requiresAuth);
    
    
  @Override
  public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException 

      
      String token  = httpServletRequest.getHeader("Authorization");      
      String secret = clientSecret;
      
      String bearer = token.replace("Bearer", "").trim();

      Algorithm algorithm = Algorithm.HMAC512(Base64.getDecoder().decode(secret));
      JWTVerifier verifier = JWT.require(algorithm)
         .withSubject("xxxx-xxxx@xxxx.id") //i'm hardcoded this for testing
          .build();

      DecodedJWT jwt = verifier.verify(bearer);
      
      UserModel user = new UserModel();
      user.setUserId(jwt.getSubject());
      
      List<GrantedAuthority> authorities =  AuthorityUtils.commaSeparatedStringToAuthorityList("");
      return new UsernamePasswordAuthenticationToken(user, null, authorities);

  
    
    
    
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult)
            throws IOException, ServletException 
        super.successfulAuthentication(request, response, chain, authResult);

        // As this authentication is in HTTP header, after success we need to continue the request normally
        // and return the response as if the resource was not secured at all
        chain.doFilter(request, response);
    
    
    

WebSecurityConfig.java

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 


 private static final RequestMatcher PROTECTED_URLS = new OrRequestMatcher(
  new AntPathRequestMatcher("/engagement/**")
 );


 @Override
 public void configure(final WebSecurity webSecurity) 
  webSecurity.ignoring()
      .antMatchers("/api/v1/auth/login")
      .antMatchers("/api/v1/auth/logout");
 

 @Override
 public void configure(HttpSecurity http) throws Exception 
      http.sessionManagement()
       .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
       .and()
       .exceptionHandling()
       .and()
       .addFilterBefore(authenticationFilter(), UsernamePasswordAuthenticationFilter.class)
       .authorizeRequests()
       .requestMatchers(PROTECTED_URLS)
       .authenticated()
       .and()
       .cors().and().csrf().disable();
     
 

 @Bean
 AuthenticationFilter authenticationFilter() throws Exception 
  final AuthenticationFilter filter = new AuthenticationFilter(PROTECTED_URLS);
  filter.setAuthenticationManager(authenticationManager());
  //filter.setAuthenticationSuccessHandler(successHandler());
  return filter;
 

 @Bean
 AuthenticationEntryPoint forbiddenEntryPoint() 
     return new HttpStatusEntryPoint(HttpStatus.FORBIDDEN);
 

WebConfig.java

@Configuration
public class WebConfig 

    @Bean
    public ServletWebServerFactory servletContainer() 

        var tomcat = new TomcatServletWebServerFactory() 

            @Override
            protected void postProcessContext(Context context) 

                var securityConstraint = new SecurityConstraint();
                securityConstraint.setUserConstraint("CONFIDENTIAL");

                var collection = new SecurityCollection();
                collection.addPattern("/*");
                securityConstraint.addCollection(collection);
                context.addConstraint(securityConstraint);
            
        ;

        tomcat.addAdditionalTomcatConnectors(redirectConnector());
        return tomcat;
    

    private Connector redirectConnector() 

        var connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setScheme("http");
        connector.setPort(8080);
        connector.setSecure(false);
        connector.setRedirectPort(8443);

        return connector;
    
     

邮递员日志


    "timestamp": "2020-07-28T06:10:52.881+00:00",
    "status": 404,
    "error": "Not Found",
    "message": "",
    "path": "/"

更新

所以我检查了邮递员控制台,它有像这张图片一样的可疑日志,我的发布方法总是以某种方式丢失,然后邮递员重定向到获取方法和根 url。

【问题讨论】:

【参考方案1】:

尝试在之后定义过滤器。

    @Override
    public void addFilters(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception 
        http
            .addFilterAfter(authenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    

【讨论】:

感谢您的建议,我已经尝试过了,但仍然面临同样的问题。

以上是关于JWT 认证成功,但是邮递员返回 404的主要内容,如果未能解决你的问题,请参考以下文章

即使令牌是在邮递员中创建的,JWT 令牌也会返回空

获取 JWT 后,带有 Spring Boot 后端的 Angular 在现有路由上返回 404

Laravel JWT 身份验证返回 False

使用虚拟主机的 Laravel API 返回 404

axios发布请求不返回响应错误

Agora 云录制无法正常工作。正常启动和获取工作,但是我没有得到任何视频文件并查询和停止返回错误404