Jquery CORS问题-编号';访问控制允许原点';请求的资源上存在标头

Jquery CORS问题-编号';访问控制允许原点';请求的资源上存在标头,jquery,spring,tomcat,spring-security,cors,Jquery,Spring,Tomcat,Spring Security,Cors,我已经创建了两个web应用程序-客户端和服务应用程序。当客户端和服务应用程序部署在同一个Tomcat实例中时,它们之间的交互很好。 但是,当应用程序部署到单独的Tomcat实例(不同的机器)中时,当请求发送服务应用程序时,我会得到以下错误 对飞行前请求的响应未通过访问控制检查:请求的资源上不存在“访问控制允许来源”标头。 起源'http://localhost:8080因此,不允许访问。响应的HTTP状态代码为401 我的客户端应用程序使用JQuery、HTML5和Bootstrap 对服务进

我已经创建了两个web应用程序-客户端和服务应用程序。
当客户端和服务应用程序部署在同一个Tomcat实例中时,它们之间的交互很好。
但是,当应用程序部署到单独的Tomcat实例(不同的机器)中时,当请求发送服务应用程序时,我会得到以下错误

对飞行前请求的响应未通过访问控制检查:请求的资源上不存在“访问控制允许来源”标头。
起源'http://localhost:8080因此,不允许访问。响应的HTTP状态代码为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 );
        });
}
我的服务应用程序使用SpringMVC、SpringDataJPA和SpringSecurity

我已经包括了
corscoConfiguration
类,如下所示:

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 );
        });
}
CORSConfig.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;
    }
}
@配置
@EnableWebMvc
公共类CORSConfig扩展WebMVCConfigureAdapter{
@凌驾
公共作废添加公司标志(公司注册处){
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安全依赖项:


org.springframework.security
spring安全配置
3.2.3.1发布
org.springframework.security
spring安全网
3.2.3.1发布

我正在使用Apache Tomcat服务器进行部署。

CORS的飞行前请求使用HTTP
选项
而不使用凭据,请参阅:

否则,发出飞行前请求。使用“方法”选项,使用“引用源”作为“覆盖引用源”,并设置“手动重定向”标志和“阻止cookies”标志,从源获取请求URL,并使用以下附加约束:

  • 包括一个访问控制请求方法标头,其标头字段值为请求方法(即使这是一个简单的方法)
  • 如果author请求头不为空,则包括一个带有as header字段值的访问控制请求头,一个以逗号分隔的头字段名称列表,这些名称按字典顺序从author请求头中提取,每个名称都转换为ASCII小写(即使一个或多个是简单头)
  • 排除作者请求头
  • 排除用户凭据
  • 排除请求实体主体
您必须允许匿名访问HTTP
选项

Spring Security 3

您的修改(和简化)代码:

@覆盖
受保护的无效配置(HttpSecurity http)引发异常{
http
.授权请求()
.antMatchers(HttpMethod.OPTIONS,“/**”).permitAll()
.antMatchers(“/login”).permitAll()
.anyRequest().fullyAuthenticated()
.及()
.httpBasic()
.及()
.会议管理()
.sessionCreationPolicy(sessionCreationPolicy.STATELESS)
.及()
.csrf().disable();
}
您仍然需要CORS配置(可能还有一些附加值):

春季安全4

由于Spring Security 4.2.0,您可以使用内置支持,请参阅:

19。CORS

Spring框架为CORS提供了一流的支持。必须在Spring Security之前处理COR,因为飞行前请求将不包含任何cookie(即
JSESSIONID
)。如果请求不包含任何cookie,并且Spring安全性是第一位的,则请求将确定用户未经过身份验证(因为请求中没有cookie),并拒绝该用户

确保首先处理CORS的最简单方法是使用
CorsFilter
。用户可以通过提供
CorsConfigurationSource
,使用以下工具将
CorsFilter
与Spring Security集成:

@EnableWebSecurity
公共类WebSecurityConfig扩展了WebSecurityConfigureAdapter{
@凌驾
受保护的无效配置(HttpSecurity http)引发异常{
http
//默认情况下,使用名为corsConfigurationSource的Bean
.cors()和()
...
}
@豆子
CorsConfiguration源CorsConfiguration源(){
CorsConfiguration配置=新的CorsConfiguration();
configuration.setAllowedOriginates(Arrays.asList(“https://example.com"));
setAllowedMethods(Arrays.asList(“GET”、“POST”));
UrlBasedCorsConfigurationSource=新的UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration(“/**”,配置);
返回源;
}
}

自Spring Security 4.1以来,这是使Spring Security支持CORS的正确方法(Spring Boot 1.4/1.5中也需要):

以及:

不要执行以下任何操作,这是尝试解决问题的错误方法:

  • http.authorizeRequests()
  • web.ignering().antMatchers(HttpMethod.OPTIONS)

参考资料:

在我的例子中,我启用了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;
}
基本上在本例中,
是有序的。最高优先级是键


不同的pom依赖项添加了不同类型的过滤器,因此我们可能会根据顺序出现问题。

这适用于:spring boot starter父版本2.2.6.RELEASE

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("*").allowedHeaders("*").allowedMethods("*");
    }
}

在prod中将“*”更改为有意义的内容

因为这些示例对我都没有帮助,所以我自己就知道了。 通常最复杂的错误总是发生在我身上。这就是我处理这个bug的方法

在这种方法中:

@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、so PUT、DELETE不会
@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;
}
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;
    }
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import java.util.Arrays;
import java.util.List;

@Component
public class CorsFilterConfig {

    public static final List<String> allowedOrigins = Arrays.asList("*");

    @Bean
    public FilterRegistrationBean<CorsFilter> initCorsFilter() {
        // @formatter:off
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type"));
        config.addAllowedMethod("*");
        config.setAllowedOrigins(allowedOrigins);
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
        // @formatter:on
    }
}
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("*");
            }
        };
    }

}