angular - 响应状态 200,但在 Angular 8 中仍然出现 CORS 错误
问题描述
我的 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));
}
谢谢大家的提示。
解决方案
如果您的 cors 请求不是GET,则浏览器将发出一个选项请求(预检请求),它不会发送身份验证标头或类似的东西。因此,在您的安全配置中,您需要允许该 url 的匿名选项请求。
推荐阅读
- vue.js - 如何在 vue.js 中构建由 npm run build 命令动态获取的图像?
- php - 奇怪的日期格式
- validation - 如果 webhook 中的查询参数中存在非英语字符/表情符号,则 Twilio webhook 验证失败
- javascript - 在 Strapi 中提供没有哈希的文件
- excel - 即使 Excel 语言设置为阿拉伯语,VBA 也无法设置 RightToLeft
- php - 如何将我的下拉值传递给 CodeIgniter 控制器?
- gitlab - 如何将 Gitlab 页面映射到端口?
- c# - 如何检查一个 int 是否可以被另一个 int 整除?使用c#,以下指定条件
- reactjs - 反应路由不起作用 - 使用 react-router-bootstrap
- python - 如何使用 Python 从分类数据制作列联表?