我创建了两个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
我的客户端应用程序使用JQuery,HTML5和Bootstrap。
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 );
});
}
我的服务应用程序使用Spring MVC,Spring Data JPA和Spring Security。
我已加入CorsConfiguration
课程,如下所示:
CORSConfig.java
:
@Configuration
@EnableWebMvc
public class CORSConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("*");
}
}
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依赖项:
<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>
我正在使用 Apache Tomcat 服务器进行部署。
答案 0 :(得分:11)
CORS的预检请求使用没有凭据的HTTP OPTIONS
,请参阅Cross-Origin Resource Sharing:
否则,请执行预检请求。使用引用来源作为覆盖引用来源,使用OPTIONS方法设置手动重定向标记和块cookie标记,并使用以下附加约束,从原始来源获取请求URL:
- 在请求方法中包含一个Access-Control-Request-Method标头作为标题字段值(即使这是一个简单的方法)。
- 如果作者请求标头不为空,则包含带有标题字段值的Access-Control-Request-Headers标头,以字典顺序排列作者请求标头中的标题字段名称的逗号分隔列表,每个标题转换为ASCII小写(甚至当一个或多个是一个简单的标题时。)
- 排除作者请求标题。
- 排除用户凭据。
- 排除请求实体正文。
您必须允许HTTP OPTIONS
的匿名访问。
您修改后的(和简化的)代码:
@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();
}
自Spring Security 4.2.0起,您可以使用内置支持,请参阅Spring Security Reference:
<强> 19。 CORS 强>
Spring Framework为CORS提供了一流的支持。必须在Spring Security之前处理CORS,因为飞行前请求不包含任何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; } }
答案 1 :(得分:8)
从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");
}
}
和
@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;
}
}
不执行以下任何操作,这是尝试解决问题的错误方法:
http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
web.ignoring().antMatchers(HttpMethod.OPTIONS);
参考:http://docs.spring.io/spring-security/site/docs/4.2.x/reference/html/cors.html
答案 2 :(得分:1)
由于这些发布的示例都没有帮助我,因此我是根据自己的知识来做事情的。 通常,最复杂的错误总是发生在我身上。因此,这就是我处理此错误的方式。
在这种方法中:
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration cors = new CorsConfiguration();
cors.setAllowedMethods(Arrays.asList("POST", "GET", "PUT", "HEAD", "DELETE"));
UrlBasedCorsConfigurationSource source = new
UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
默认情况下,CorsConfiguration允许以下方法:POST,HEAD,GET,因此,PUT,DELETE将不起作用!我要做的是创建新的CorsConfiguration实例并设置允许的方法:
cors.setAllowedMethods(Arrays.asList("POST", "GET", "PUT", "HEAD", "DELETE"));
所以现在我的方法如下:
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration cors = new CorsConfiguration();
cors.setAllowedMethods(Arrays.asList("POST", "GET", "PUT", "HEAD", "DELETE"));
UrlBasedCorsConfigurationSource source = new
UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", cors.applyPermitDefaultValues());
return source;
}
,它就像魅力。希望对您有所帮助。当然,所有其他配置都是由spring.io文档进行的
答案 3 :(得分:0)
在我的情况下,我启用了资源服务器并启用了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;
}
基本上在这个例子中Ordered.HIGHEST_PRECEDENCE
是关键!
{{3}}
各种pom依赖项会添加不同类型的过滤器,因此我们可能会遇到基于订单的问题。
答案 4 :(得分:0)
这适用于:spring-boot-starter-parent 2.2.6.RELEASE
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*").allowedMethods("*");
}
}
将“ *”更改为产品中有意义的内容
答案 5 :(得分:0)
在主应用程序中添加以下配置。它在 spring boot应用程序2.3.1
中起作用JavaRDD<Integer> mappartRdd = DF.repartition(3).javaRDD().mapPartitions(it-> Arrays.asList(JavaConversions.asScalaIterator(it).length()).iterator());
StructType schema = new StructType()
.add(new StructField("value", DataTypes.IntegerType, true, Metadata.empty()));
Dataset<Row> df = spark.createDataFrame(mappartRdd.map(RowFactory::create), schema);
df.show(false);
df.printSchema();
/**
* +-----+
* |value|
* +-----+
* |6 |
* |8 |
* |6 |
* +-----+
*
* root
* |-- value: integer (nullable = true)
*/
答案 6 :(得分:0)
尝试一下:
editorTheme
答案 7 :(得分:0)
在主应用程序中添加以下配置。它在 spring boot 应用程序 2.3.1
中对我有用package com.example.restservicecors;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@SpringBootApplication
public class RestServiceCorsApplication {
public static void main(String[] args) {
SpringApplication.run(RestServiceCorsApplication.class, args);
}
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*").allowedMethods("*");
}
};
}
}