jQuery CORS 问题 - 请求的资源上不存在“Access-Control-Allow-Origin”标头
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42016126/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CORS issue - No 'Access-Control-Allow-Origin' header is present on the requested resource
提问by JavaDeveloper
I have created two web applications - client and service apps.
The interaction between client and service apps goes fine when they are deployed in same Tomcat instance.
But when the apps are deployed into seperate Tomcat instances (different machines), I get the below error when request to sent service app.
我创建了两个 Web 应用程序 - 客户端和服务应用程序。
当客户端和服务应用程序部署在同一个 Tomcat 实例中时,它们之间的交互会很好。
但是当应用程序部署到单独的 Tomcat 实例(不同的机器)时,当请求发送服务应用程序时,我收到以下错误。
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 401
My Client application uses JQuery, HTML5 and Bootstrap.
我的客户端应用程序使用 JQuery、HTML5 和 Bootstrap。
AJAX call is made to service as shown below:
对服务进行 AJAX 调用,如下所示:
var auth = "Basic " + btoa({usname} + ":" + {password});
var service_url = {serviceAppDomainName}/services;
if($("#registrationForm").valid()){
var formData = JSON.stringify(getFormData(registrationForm));
$.ajax({
url: service_url+action,
dataType: 'json',
async: false,
type: 'POST',
headers:{
"Authorization":auth
},
contentType: 'application/json',
data: formData,
success: function(data){
//success code
},
error: function( jqXhr, textStatus, errorThrown ){
alert( errorThrown );
});
}
My service application uses Spring MVC, Spring Data JPA and Spring Security.
我的服务应用程序使用 Spring MVC、Spring Data JPA 和 Spring Security。
I have included CorsConfiguration
class as shown below:
我已经包含了CorsConfiguration
如下所示的类:
CORSConfig.java
:
CORSConfig.java
:
@Configuration
@EnableWebMvc
public class CORSConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("*");
}
}
SecurityConfig.java
:
SecurityConfig.java
:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@ComponentScan(basePackages = "com.services", scopedProxy = ScopedProxyMode.INTERFACES)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("authenticationService")
private UserDetailsService userDetailsService;
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
auth.authenticationProvider(authenticationProvider());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().fullyAuthenticated();
http.httpBasic();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.csrf().disable();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
}
Spring Security dependencies:
Spring Security 依赖项:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.2.3.RELEASE</version>
</dependency>
I am using Apache Tomcatserver for deployment.
我正在使用Apache Tomcat服务器进行部署。
采纳答案by dur
CORS' preflight request uses HTTP OPTIONS
without credentials, see Cross-Origin Resource Sharing:
CORS 的预检请求使用OPTIONS
没有凭据的HTTP ,请参阅跨源资源共享:
Otherwise, make a preflight request. Fetch the request URL from origin source origin using referrer source as override referrer source with the manual redirect flag and the block cookies flag set, using the method OPTIONS, and with the following additional constraints:
- Include an Access-Control-Request-Method header with as header field value the request method (even when that is a simple method).
- If author request headers is not empty include an Access-Control-Request-Headers header with as header field value a comma-separated list of the header field names from author request headers in lexicographical order, each converted to ASCII lowercase (even when one or more are a simple header).
- Exclude the author request headers.
- Exclude user credentials.
- Exclude the request entity body.
否则,发出预检请求。使用引用源作为覆盖引用源,使用手动重定向标志和阻止 cookie 标志设置,使用方法 OPTIONS 和以下附加约束,从源源源获取请求 URL:
- 包含一个 Access-Control-Request-Method 标头,其中包含请求方法的标头字段值(即使这是一个简单的方法)。
- 如果作者请求标头不为空,则包括一个 Access-Control-Request-Headers 标头,标头字段值为逗号分隔的标头字段名称列表,按字典顺序来自作者请求标头,每个标头都转换为 ASCII 小写(即使有一个或更多是一个简单的标题)。
- 排除作者请求标头。
- 排除用户凭据。
- 排除请求实体正文。
You have to allow anonymous access for HTTP OPTIONS
.
您必须允许匿名访问 HTTP OPTIONS
。
Your modified (and simplified) code:
您修改(和简化)的代码:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.andMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers("/login").permitAll()
.anyRequest().fullyAuthenticated()
.and()
.httpBasic()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable();
}
Since Spring Security 4.2.0 you can use the built-in support, see Spring Security Reference:
从 Spring Security 4.2.0 开始,您可以使用内置支持,请参阅Spring Security Reference:
19. CORS
Spring Framework provides first class support for CORS. CORS must be processed before Spring Security because the pre-flight request will not contain any cookies (i.e. the
JSESSIONID
). If the request does not contain any cookies and Spring Security is first, the request will determine the user is not authenticated (since there are no cookies in the request) and reject it.The easiest way to ensure that CORS is handled first is to use the
CorsFilter
. Users can integrate theCorsFilter
with Spring Security by providing aCorsConfigurationSource
using the following:@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http // by default uses a Bean by the name of corsConfigurationSource .cors().and() ... } @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("https://example.com")); configuration.setAllowedMethods(Arrays.asList("GET","POST")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } }
19.CORS
Spring Framework 为 CORS 提供了一流的支持。CORS 必须在 Spring Security 之前处理,因为飞行前请求将不包含任何 cookie(即
JSESSIONID
)。如果请求不包含任何 cookie 并且 Spring Security 是第一个,则请求将确定用户未通过身份验证(因为请求中没有 cookie)并拒绝它。确保首先处理 CORS 的最简单方法是使用
CorsFilter
. 用户可以CorsFilter
通过提供CorsConfigurationSource
以下内容与 Spring Security集成:@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http // by default uses a Bean by the name of corsConfigurationSource .cors().and() ... } @Bean CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("https://example.com")); configuration.setAllowedMethods(Arrays.asList("GET","POST")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } }
回答by Hendy Irawan
Since Spring Security 4.1, this is the proper way to make Spring Security support CORS (also needed in Spring Boot 1.4/1.5):
从 Spring Security 4.1 开始,这是使 Spring Security 支持 CORS 的正确方法(Spring Boot 1.4/1.5 中也需要):
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH");
}
}
and:
和:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// http.csrf().disable();
http.cors();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(ImmutableList.of("*"));
configuration.setAllowedMethods(ImmutableList.of("HEAD",
"GET", "POST", "PUT", "DELETE", "PATCH"));
// setAllowCredentials(true) is important, otherwise:
// The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
configuration.setAllowCredentials(true);
// setAllowedHeaders is important! Without it, OPTIONS preflight request
// will fail with 403 Invalid CORS request
configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Do notdo any of below, which are the wrong way to attempt solving the problem:
千万不能做任何的下方,这是错误的方式来尝试解决问题:
http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
web.ignoring().antMatchers(HttpMethod.OPTIONS);
http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
web.ignoring().antMatchers(HttpMethod.OPTIONS);
Reference: http://docs.spring.io/spring-security/site/docs/4.2.x/reference/html/cors.html
参考:http: //docs.spring.io/spring-security/site/docs/4.2.x/reference/html/cors.html
回答by AntonIva
In my case, I have Resource Server with OAuth security enabled and any of above solutions didn't work. After some debugging and googling figured why.
就我而言,我的资源服务器启用了 OAuth 安全性,但上述任何解决方案均无效。经过一些调试和谷歌搜索后找到了原因。
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
Basically in this example Ordered.HIGHEST_PRECEDENCE
is key!
基本上在这个例子中Ordered.HIGHEST_PRECEDENCE
是关键!
https://github.com/spring-projects/spring-security-oauth/issues/938
https://github.com/spring-projects/spring-security-oauth/issues/938
Various pom dependencies add different kinds of filters and therefore we could have issues based on order.
各种 pom 依赖项添加了不同类型的过滤器,因此我们可能会遇到基于顺序的问题。