我已经创建了两个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如下所示的类:
CorsConfiguration
CORSConfig.java:
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服务器进行部署。
CORS的预检请求使用OPTIONS不带凭据的HTTP ,请参阅跨域资源共享:
OPTIONS
否则,请发出预检请求。使用方法OPTIONS和以下附加约束,使用引荐来源来源作为覆盖引荐来源,并设置了手动重定向标志和块cookie标志,从起源来源起点获取请求URL:
你必须允许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:
Spring Framework为CORS提供了一流的支持。必须在Spring Security之前处理CORS,因为飞行前请求将不包含任何cookie(即JSESSIONID)。如果请求不包含任何cookie,并且首先使用Spring Security,则该请求将确定用户未通过身份验证(因为请求中没有cookie),并拒绝该用户。
JSESSIONID
确保首先处理CORS的最简单方法是使用CorsFilter。用户可以CorsFilter通过CorsConfigurationSource使用以下命令将集成到Spring Security中:
CorsFilter
CorsConfigurationSource
@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; } }