为 JWT 使用过滤器时,HttpServletRequest 为空,标头适用于邮递员,但不适用于 localhost

Posted

技术标签:

【中文标题】为 JWT 使用过滤器时,HttpServletRequest 为空,标头适用于邮递员,但不适用于 localhost【英文标题】:HttpServletRequest is null when using filter for JWT, headers work on postman but not localhost 【发布时间】:2020-08-08 14:10:41 【问题描述】:

我将 React 用于前端,Java spring boot 用于后端。在我使用 Bcrypt 对密码进行编码之前,我的 api 正在工作,但现在在每次响应为空的 api 调用之前,内部过滤器似乎存在问题......

这是我的 WebSecurityConfig.java


@EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter 
        @Autowired
        private UserDetailsService myUserDetailsService;
        @Autowired
        private JwtRequestFilter jwtRequestFilter;

        @Autowired
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception 
            auth.userDetailsService(myUserDetailsService).passwordEncoder(passwordEncode());
        

        @Bean
        public PasswordEncoder passwordEncode()
            return new BCryptPasswordEncoder();
        

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

        @Override
        protected void configure(HttpSecurity httpSecurity) throws Exception 
            httpSecurity.csrf().disable()
                    .authorizeRequests().antMatchers("/authenticate").permitAll()
                    .antMatchers("/personInfo").permitAll()
                    .antMatchers("/signup").permitAll().
                            anyRequest().authenticated().and().
            addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class).exceptionHandling();

        

    

这是我的 JWTRequestFilter.java

我认为这可能与 passwordEncoder() 有关,因为当我不使用 BcryptPasswordEncoder() 时我的调用正在工作...

@Component
public class JwtRequestFilter extends OncePerRequestFilter 

    @Autowired
    private MyUserDetailsService userDetailsService;

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException 

        if(request == null)
            System.out.println("request is null");
        

        final String authorizationHeader = request.getHeader("Authorization");

        String username = null;
        String jwt = null;

        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) 
            jwt = authorizationHeader.substring(7);
            username = jwtUtil.extractUsername(jwt);
        

        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) 

            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

            if (jwtUtil.validateToken(jwt, userDetails)) 

                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            
        
        chain.doFilter(request, response);
    



我在前端使用 react 并使用 axios 调用

async totals()
        console.log('Bearer ', localStorage.getItem('id_token'));
        let data = await axios.get("http://localhost:8080/totals", 
            headers: 
                'Content-Type': 'application/json',
                'Authorization': 'Bearer ' + localStorage.getItem('id_token')
            
        )
            .then(this._checkStatus);

        return data.request.response;
    

当我在邮递员中使用令牌时,api 工作,所以问题出在初始请求和过滤器之间......

我得到的错误是 - 从源“http://localhost:3000”访问“http://localhost:8080/totals”处的 XMLHttpRequest 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:它没有 HTTP ok 状态。

感谢您的宝贵时间:)

【问题讨论】:

【参考方案1】:

如果有人遇到同样的问题,我通过在 WebSecurityConfig.java 中的 configure(HttpSecurity httpSecurity) 方法末尾添加这一行来解决它

httpSecurity.cors();

:)

【讨论】:

以上是关于为 JWT 使用过滤器时,HttpServletRequest 为空,标头适用于邮递员,但不适用于 localhost的主要内容,如果未能解决你的问题,请参考以下文章

JWT 与 OAuth 2.0 有何不同?

如何在 JWT 过滤器中将 api 列入白名单

在 Spring Boot 2 上实现基于过滤器的 JWT 身份验证与 OAuth2 JWT 身份验证

前后端分离的Web应用程序中使用Spring Security+Mybatis+JWT非对称加密+动态权限管理:身份验证过滤器

不使用 UsernamePasswordAuthenticationToken 的 Spring Security JWT 验证

我需要一个单独的 JWT 过滤器来进行多次登录吗?