Spring Security 为什么REST风格的Web服务返回错误401?

9rnv2umw  于 2023-02-16  发布在  Spring
关注(0)|答案(1)|浏览(156)

更新

由于被推动实现调试日志,我现在可以看到问题是Spring报告了一个为notices控制器找到的无效CSRF令牌。到目前为止,我已经检查了postman生成的头文件,并将它们与通过获取请求生成的头文件进行了比较,未发现差异。生成的令牌已成功放入请求标头中。不幸的是,Spring日志中没有任何可辨别的内容,因此调试继续进行。
我正在学习Spring Security,目前正在将前端React部分连接到Spring后端。我遇到了麻烦,因为当向所需端点发出POST请求时,它返回错误401。这让我很困惑,因为我相信我已经正确配置了CORS,并且还将端点标记为允许所有端点。
简而言之,该进程调用端点/token以获取CSRF令牌,然后调用/notices并将令牌作为头文件传入。如果使用Postman完成,该进程将按预期工作,因此我认为这是CORS问题,但是,我尝试在不同端口上运行前端,它被CORS阻止,因此我认为问题在其他地方。
一些附加信息:

  • /notices/token都是POST操作。
  • Spring后端和React前端都在同一台本地机器上运行。
  • 收到错误代码401

前端JavaScript调用的代码为:

const debugNotices = () => {
  let tokenData:any;
  fetch('http://localhost:8080/token', {method:"POST"})
  .then((response) => response.json())
  .then((data) => tokenData = data).then((data:any) => fetch("http://localhost:8080/notices", 
  {
    method:"POST",
    headers: {
      "X-XSRF-TOKEN": tokenData.token
    }
  }))

}

Spring安全配置:

@Bean
SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        
    http
        .cors()
            .configurationSource(new CorsConfigurationSource() {
            
                @Override
                public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
                    CorsConfiguration config = new CorsConfiguration();
                    
                    config.setAllowedOrigins(Collections.singletonList("http://localhost:3000"));
                    config.setAllowedMethods(Collections.singletonList(("*")));
                    config.setAllowCredentials(true);
                    config.setAllowedHeaders(Collections.singletonList("*"));
                    config.setMaxAge(3600L);
                    return config;
                }
            })
            .and()
        .csrf()
            .ignoringRequestMatchers("/contact", "/register", "/token")
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) 
            .and()
        .securityContext()
            .requireExplicitSave(false)
            .and()
        .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
            .and()
        .authorizeHttpRequests()
            .requestMatchers("/myAccount", "/myBalance", "/myLoans", "/myCards", "/user").authenticated()
            .requestMatchers("/notices", "/contact", "/register", "/test", "/token").permitAll()
            .and()
        .httpBasic()
            .and()
        .formLogin();
        
    return http.build();
}

我试过在请求正文中包含credentials:'include',但是它会导致一个登录提示,我不相信这是我要找的方向。
我还尝试过手动插入CSRF令牌,而不是从服务器请求数据,但都失败了。
我还测试了CORS,就我所知,从localhost:3000以外的任何地方访问端点都会被拒绝,并出现预期的CORS错误。

4dbbbstv

4dbbbstv1#

此问题仅在从 localhost:portNumber 访问React前端时发生,我能够通过使用本地IP地址代替localhost来完全解决此问题。

  • 192.168.0.105:3000* 的数据库。

我仍然不确定为什么在URL中使用localhost会有问题,如果你知道的话,我很想听听为什么会发生这种情况。

相关问题