我一直试图弄清楚为什么跨源请求仅在Firefox中失败。事实证明Firefox不会在跨源XHR上发送SSL / TLS凭证,这显然是由W3 CORS Spec定义的。通过在我的客户端代码中为我的XHR实例添加withCredentials: true
,我能够 解决这个问题(适用于GET,PUT,POST,DELETE等)。
然而,尽管我在XHR中明确告知,但Firefox仍然拒绝为飞行前的OPTIONS请求添加凭据。除非以某种方式在客户端代码中执行此操作,否则我将配置我的服务器以允许未经身份验证的OPTIONS请求(在双向SSL配置中对我来说似乎很疯狂)。这里有安全隐患吗?
我们的服务器是一个使用Spring Security的Spring Boot项目,并使用X509安全证书配置为双向SSL。我将提供所有相关代码,以便您了解应用程序的配置方式。
主要课程:
@EnableAutoConfiguration
@SpringBootApplication
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class OurApp extends WebSecurityConfigurerAdapter {
@Autowired
OurUserDetailsService ourUserDetailsService;
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext ctx = SpringApplication.run(OurApp.class, args);
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// X509Configurer<HttpSecurity> x509Configurer = http.authorizeRequests().anyRequest().authenticated().and().x509();
http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll().
.anyRequest().authenticated()
.and()
.x509().subjectPrincipalRegex("(.*)").authenticationUserDetailsService(ourUserDetailsService)
.and()
.cors()
.and()
.csrf().disable();
}
}
具有CORS设置的配置类:
@Configuration
public class OurConfig {
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("https://client-origin"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"));
configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type", "Access-Control-Allow-Origin",
"Access-Control-Allow-Headers", "X-Requested-With", "requestId", "Correlation-Id"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
public IgnoredRequestCustomizer optionsIgnoredRequestsCustomizer() {
return configurer -> {
List<RequestMatcher> matchers = new ArrayList<>();
matchers.add(new AntPathRequestMatcher("/**", "OPTIONS"));
configurer.requestMatchers(new OrRequestMatcher(matchers));
};
}
}
这适用于所有GET请求,当我在浏览器中为其他动词手动执行请求时 - OPTIONS除外。预检请求在TLS握手期间继续失败,并由Firefox中止。我很困惑,甚至可以通过(双向SSL)HTTPS发送未经过身份验证(无凭证)的请求吗?
如何配置spring security或spring boot以允许使用双向SSL(通过HTTPS)配置启用未经身份验证的OPTIONS请求?
答案 0 :(得分:1)
预检请求应排除凭据,请参阅CORS specification:
7.1.5带预检的跨源请求
为了保护资源免受在此规范存在之前不能源自某些用户代理的跨源请求的影响,执行预检请求以确保资源知道此规范。此请求的结果存储在预检结果缓存中。
以下步骤描述了用户代理必须为具有预检的跨源请求执行的操作。这是对非同源URL的请求,首先需要使用预检结果缓存条目或预检请求进行授权。
[...]
- 排除用户凭据。
要处理没有凭据的预检请求(SSL客户端证书),您必须更改服务器的SSL配置。
例如,请参阅Spring Boot Reference Guide:
server.ssl.client-auth= # Whether client authentication is wanted ("want") or needed ("need"). Requires a trust store.