【问题标题】:Autorization token from React doesn't pass Java Spring Boot filter来自 React 的授权令牌未通过 Java Spring Boot 过滤器
【发布时间】:2021-10-31 19:36:16
【问题描述】:

我正在构建一个应用程序,该应用程序在 Java Spring boot 中具有后端,在 React 中具有前端。为了将令牌从客户端传递到服务器,我使用了一个如下所示的过滤器类:

@Component
@Order(1)
public class ApplicationFilter implements Filter {
    @Autowired
    private UserDetails userDetails;
    
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        
        String token = httpRequest.getHeader("Authorization").substring(7);
        
        Jws<Claims> jwsParsed = null;
        try {
             jwsParsed = Jwts.parserBuilder()
                    .setSigningKey("Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E=".getBytes())
                    .build()
                    .parseClaimsJws(token);

        } catch (Exception e) {
            throw new AuthenticationException("The token is not correct.");
        }

        Long id = jwsParsed.getBody().get("id", Long.class);
        String name = jwsParsed.getBody().get("name", String.class);
        
        userDetails.setUserId(id);
        userDetails.setUserName(name);
        
        chain.doFilter(httpRequest, response);
    }

除此之外,我正在配置网络配置:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer{

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedMethods("PUT", "DELETE","POST","GET")
                .allowedOrigins("*")
                .exposedHeaders("*");
    }
}

让请求通过 CORS 策略。而且我还配置了上下文侦听器以在应用程序中使用请求上下文:

@Configuration
public class RequestContextListenerConfig {
    @Bean
    @Order(0)
    public RequestContextListener requestContextListener() {
        return new RequestContextListener();
    }
}

块引用

在客户端,我定义了一个身份验证服务:

class AuthApiService {
    api = null;

    constructor() {
        this.api = axios.create();

        this.api
            .interceptors
            .request
            .use(config => {
                config.baseURL = "http://localhost:8080/";
                config.headers = {
                    Authorization: `Bearer ${loginService.getUserToken()}`
                };
                return config;
            });
    }

    getApi = () => this.api;
}

const authApiService = new AuthApiService();
export const authApi = authApiService.getApi();
export default authApiService;

并像这样在我的请求中使用它:

addItem(item) {
authApi.post("image", item)
    .then((response) => {
        item.id = response.data.id;
        this.galleryItems.push(item);
        this.dataWasChanged.next("ADD");
    }).catch((err) => {
        console.error(err.response);
    });
}

问题是当我运行这个添加函数时,它在控制台中给我一个错误:

Access to XMLHttpRequest at 'http://localhost:8080/' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

在java中也是如此:

ERROR 46280 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
Cannot invoke "String.substring(int)" because the return value of "javax.servlet.http.HttpServletRequest.getHeader(String)" is null

我更确定令牌已发送,因为在出​​现错误之前我看到它打印在控制台中。此外,当我通过 Postman 访问应用程序时,一切都使用令牌。

我从 Postman 打印了标题,它们是:

Header 'authorization' = Bearer eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbGdhIiwic3ViIjoiZ2FsbGVyeUFwcCIsImlkIjoyLCJuYW1lIjoiTWF4IiwiaWF0IjoxNjM1MTkwMDA5LCJleHAiOjE2Mzc4NzIwMDl9.KV7PNXDIITMQcmzsLOF0WMF34-t4PP47URMoiGJYvvs
Header 'content-type' = application/json
Header 'user-agent' = PostmanRuntime/7.28.4
Header 'accept' = */*
Header 'postman-token' = 21eee286-c554-442f-a169-ab82926165f7
Header 'host' = localhost:8080
Header 'accept-encoding' = gzip, deflate, br
Header 'connection' = keep-alive
Header 'content-length' = 85

但是从浏览器请求中我看到了这些标头:

host: localhost:8080
connection: keep-alive
accept: */*
access-control-request-method: POST
access-control-request-headers: authorization,content-type
origin: http://localhost:3000
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
sec-fetch-mode: cors
sec-fetch-site: same-site
sec-fetch-dest: empty
referer: http://localhost:3000/
accept-encoding: gzip, deflate, br
accept-language: ru-RU,ru;q=0.9,en;q=0.8,he;q=0.7

根本没有授权标头。

所以问题是为什么授权令牌没有来自 react 客户端的 java 代码?我做错了什么,哪里可能是错误?或者有没有其他方法可以从我发送到服务器的标头中接收令牌?

【问题讨论】:

    标签: reactjs spring-boot authorization token client-server


    【解决方案1】:

    preflight request 似乎被 Spring Security 过滤器阻止了。 您将需要额外的CORS configuration for Spring Security

    @Configuration
    // unnecessary in most cases
    // https://docs.spring.io/spring-boot/docs/2.5.6/reference/htmlsingle/#features.developing-web-applications.spring-mvc.auto-configuration
    // @EnableWebMvc
    public class WebConfig implements WebMvcConfigurer{
    
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedMethods("PUT", "DELETE","POST","GET")
                    .allowedOrigins("*")
                    .exposedHeaders("*");
        }
    }
    
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
     @Override
     protected void configure(final HttpSecurity http) throws Exception {
         // if disabling CSRF protection
         // https://docs.spring.io/spring-security/site/docs/5.5.3/reference/html5/#csrf-when
         http.csrf().disable();
    
         // if Spring MVC is on classpath and no CorsConfigurationSource is provided,
         // Spring Security will use CORS configuration provided to Spring MVC
         http.cors(Customizer.withDefaults());
     }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-05-28
      • 2020-12-22
      • 2014-06-30
      • 1970-01-01
      • 2018-11-08
      • 2013-04-11
      • 2017-12-25
      • 2018-06-13
      • 1970-01-01
      相关资源
      最近更新 更多