【问题标题】:Response status 200, but still got CORS error in Angular 8 [duplicate]响应状态 200,但在 Angular 8 中仍然出现 CORS 错误 [重复]
【发布时间】:2020-03-12 11:49:26
【问题描述】:

我的 Angluar 8 应用程序出现 CORS 错误问题。

我从服务器收到状态为 200 和有效 JWT 令牌的响应,我认为这意味着服务器配置正确,但控制台中仍然出现错误:

Access to XMLHttpRequest at 'http://localhost:8080/login' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Angular 应用程序在我的机器上本地运行,端口为 4200

服务器是我自己的带有安全性的 Spring Boot 应用程序,也在端口 8080 上本地运行

我已经实现了自定义安全过滤器来处理 CORS:

@Component
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        response.setHeader("Access-Control-Allow-Origin", "http://localhost:4200");
        response.setHeader("Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Max-Age", "180");

        filterChain.doFilter(servletRequest, servletResponse);
    }
}

并添加到安全配置中:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final RestAuthenticationSuccessHandler authenticationSuccessHandler;
    private final RestAuthenticationFailureHandler authenticationFailureHandler;
    private final CustomUserDetailsService userDetailsService;
    private final String secret;
    private final TenantFilter tenantFilter;
    private final CorsFilter corsFilter;
    private final UserTenantRelationRepository userTenantRelationRepository;

    @Autowired
    public SecurityConfig(RestAuthenticationSuccessHandler authenticationSuccessHandler,
                          RestAuthenticationFailureHandler authenticationFailureHandler,
                          CustomUserDetailsService userDetailsService,
                          @Value("${jwt.secret}") String secret, TenantFilter tenantFilter, CorsFilter corsFilter, UserTenantRelationRepository userTenantRelationRepository) {
        this.authenticationSuccessHandler = authenticationSuccessHandler;
        this.authenticationFailureHandler = authenticationFailureHandler;
        this.userDetailsService = userDetailsService;
        this.secret = secret;
        this.tenantFilter = tenantFilter;
        this.corsFilter = corsFilter;
        this.userTenantRelationRepository = userTenantRelationRepository;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .addFilterBefore(corsFilter, SessionManagementFilter.class)
                .addFilterBefore(tenantFilter, BasicAuthenticationFilter.class)
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/login").permitAll()
                .antMatchers("/register").permitAll()
                .anyRequest().authenticated()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .addFilter(authenticationFilter(userTenantRelationRepository))
                .addFilter(new JwtAuthorizationFilter(authenticationManager(), userDetailsService, secret))
                .exceptionHandling()
                .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
    }

正如我之前提到的,我收到响应 200 和有效的 JWT 令牌,所以我对此感到非常困惑。

编辑

好的,所以我已经阅读了您提到的预检请求,并修复了我的过滤器以处理此请求。

现在看起来像这样:

@Component
public class CorsFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "authorization, content-type, xsrf-token");
        response.addHeader("Access-Control-Expose-Headers", "xsrf-token");
        if ("OPTIONS".equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            filterChain.doFilter(request, response);
        }
    }
}

现在配置如下:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .addFilterBefore(corsFilter, ChannelProcessingFilter.class)
                .addFilterBefore(tenantFilter, BasicAuthenticationFilter.class)
                .csrf().disable()
                .anonymous().disable()
                .authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/login").permitAll()
                .antMatchers("/register").permitAll()
                .anyRequest().authenticated()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .addFilter(authenticationFilter(userTenantRelationRepository))
                .addFilter(new JwtAuthorizationFilter(authenticationManager(), userDetailsService, secret))
                .exceptionHandling()
                .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
    }

谢谢大家的提示。

【问题讨论】:

  • 你能发布登录控制器的代码吗?

标签: angular spring-boot spring-security cors jwt


【解决方案1】:

如果您的 cors 请求不是 GET,浏览器将发出一个选项请求 (preflight request),它不会发送身份验证标头或类似的东西。因此,在您的安全配置中,您需要允许该 url 的匿名选项请求。

【讨论】:

  • 如果您提供示例代码让 OP 在 Spring Boot 中执行此操作,将会更有帮助。
  • 我有 0 次使用 java、ant 或 spring 的经验。检查this
【解决方案2】:

我建议您使用FilterRegistrationBean 在后端进行 Cors 配置。用法如下,

@Bean

public FilterRegistrationBean<CorsFilter> corsFilter() {

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

    CorsConfiguration config = new CorsConfiguration();

    config.setAllowCredentials(true);

    config.addAllowedOrigin("http://localhost:4200");

    config.addAllowedHeader("*");

    config.addAllowedMethod("*");

    source.registerCorsConfiguration("/**", config);

    FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<CorsFilter>(

            new CorsFilter(source));

    bean.setOrder(0);

    return bean;

}

导入使用,

import org.springframework.boot.web.servlet.FilterRegistrationBean;

在具有@Configuration 注释的 WebConfig.java 文件中执行此操作。

【讨论】:

    猜你喜欢
    • 2021-11-16
    • 2021-09-21
    • 2020-05-05
    • 2021-03-01
    • 2019-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-19
    相关资源
    最近更新 更多