乐趣区

关于前端:如何解决前端访问跨域问题

一、跨域 (CORS) 反对:
Spring Framework 4.2 GA 为 CORS 提供了第一类反对,使您比通常的基于过滤器的解决方案更容易和更弱小地配置它。所以 springMVC 的版本要在 4.2 或以上版本才反对 @CrossOrigin

二、应用办法:
1、controller 配置 CORS
1.1、controller 办法的 CORS 配置,您能够向 @RequestMapping 注解处理程序办法增加一个 @CrossOrigin 注解,以便启用 CORS(默认状况下,@CrossOrigin 容许在 @RequestMapping 注解中指定的所有源和 HTTP 办法):

@RestController
@RequestMapping(“/account”) public class AccountController {

@CrossOrigin
@GetMapping("/{id}") public Account retrieve(@PathVariable Long id) {// ...

}

@DeleteMapping("/{id}") public void remove(@PathVariable Long id) {// ...

}
}
其中 @CrossOrigin 中的 2 个参数:

origins:容许可拜访的域列表

maxAge:筹备响应前的缓存继续的最大工夫(以秒为单位)。

1.2、为整个 controller 启用 @CrossOrigin

@CrossOrigin(origins = “http://domain2.com”, maxAge = 3600)
@RestController
@RequestMapping(“/account”) public class AccountController {

@GetMapping("/{id}") public Account retrieve(@PathVariable Long id) {// ...

}

@DeleteMapping("/{id}") public void remove(@PathVariable Long id) {// ...

}
}
在这个例子中,对于 retrieve()和 remove()解决办法都启用了跨域反对,还能够看到如何应用 @CrossOrigin 属性定制 CORS 配置。

1.3、同时应用 controller 和办法级别的 CORS 配置,Spring 将合并两个正文属性以创立合并的 CORS 配置。

@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping(“/account”) public class AccountController {

@CrossOrigin(origins = "http://domain2.com")
@GetMapping("/{id}") public Account retrieve(@PathVariable Long id) {// ...

}

@DeleteMapping("/{id}") public void remove(@PathVariable Long id) {// ...

}
}
1.4、如果您正在应用 Spring Security,请确保在 Spring 安全级别启用 CORS,并容许它利用 Spring MVC 级别定义的配置。

@EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override protected void configure(HttpSecurity http) throws Exception {http.cors().and()...}

}
2、全局 CORS 配置
除了细粒度、基于正文的配置之外,您还可能须要定义一些全局 CORS 配置。这相似于应用筛选器,但能够申明为 Spring MVC 并联合细粒度 @CrossOrigin 配置。默认状况下,所有 origins and GET, HEAD and POST methods 是容许的。

JavaConfig

使整个应用程序的 CORS 简化为:

@Configuration
@EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter {

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

}
如果您正在应用 Spring Boot,倡议将 WebMvcConfigurer bean 申明如下:

@Configuration public class MyConfiguration {

@Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurerAdapter() {@Override public void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**");
        }
    };
}

}
您能够轻松地更改任何属性,以及仅将此 CORS 配置利用到特定的门路模式:

@Override public void addCorsMappings(CorsRegistry registry) {

registry.addMapping("/api/**")
    .allowedOrigins("http://domain2.com")
    .allowedMethods("PUT", "DELETE")
        .allowedHeaders("header1", "header2", "header3")
    .exposedHeaders("header1", "header2")
    .allowCredentials(false).maxAge(3600);

}
如果您正在应用 Spring Security,请确保在 Spring 安全级别启用 CORS,并容许它利用 Spring MVC 级别定义的配置。

3、XML 命名空间
还能够将 CORS 与 MVC XML 命名空间配置。

a、如果整个我的项目所有办法都能够拜访,则能够这样配置;此最小 XML 配置使 CORS 在 /** 门路模式具备与 JavaConfig 雷同的缺省属性:

<mvc:cors>

<mvc:mapping path="/**" />

</mvc:cors>
其中 示意匹配到下一层; 示意前面不论有多少层,都能匹配。*

如:

<mvc:cors>

<mvc:mapping path="/api/*"/>  

</mvc:cors>
这个能够匹配到的门路有:

/api/aaa

/api/bbbb
不能匹配的:

/api/aaa/bbb
因为 * 只能匹配到下一层门路,如果想前面不论多少层都能够匹配,配置如下:

<mvc:cors>

<mvc:mapping path="/api/**"/>  

</mvc:cors>
注:其实就是一个 () 变成两个(*)

b、也能够用定制属性申明几个 CORS 映射:

<mvc:cors>

<mvc:mapping path="/api/**" allowed-origins="http://domain1.com, http://domain2.com" allowed-methods="GET, PUT" allowed-headers="header1, header2, header3" exposed-headers="header1, header2" allow-credentials="false" max-age="123" />

<mvc:mapping path="/resources/**" allowed-origins="http://domain1.com" />

</mvc:cors>
申请门路有 /api/,办法示例如下:

@RequestMapping(“/api/crossDomain”)
@ResponseBody public String crossDomain(HttpServletRequest req, HttpServletResponse res, String name){

……  
……  

}
c、如果应用 Spring Security,不要遗记在 Spring 安全级别启用 CORS:

<http>

<!-- Default to Spring MVC's CORS configuration -->
<cors /> ... </http>

4、How does it work?
CORS 申请(包含预选的带有选项办法)被主动发送到注册的各种 HandlerMapping。它们解决 CORS 筹备申请并拦挡 CORS 简略和理论申请,这得益于 CorsProcessor 实现(默认状况下默认 DefaultCorsProcessor 处理器),以便增加相干的 CORS 响应头(如 Access-Control-Allow-Origin)。CorsConfiguration 容许您指定 CORS 申请应该如何解决:容许 origins, headers, methods 等。

a、AbstractHandlerMapping#setCorsConfiguration() 容许指定一个映射,其中有几个 CorsConfiguration 映射在门路模式上,比方 /api/**。

b、子类能够通过重写 AbstractHandlerMapping 类的 getCorsConfiguration(Object, HttpServletRequest)办法来提供本人的 CorsConfiguration。

c、处理程序能够实现 CorsConfigurationSource 接口(如 ResourceHttpRequestHandler),以便为每个申请提供一个 CorsConfiguration。

5、基于过滤器的 CORS 反对
作为上述其余办法的代替,Spring 框架还提供了 CorsFilter。在这种状况下,不必应用 @CrossOrigin 或 WebMvcConfigurer#addCorsMappings(CorsRegistry),例如,能够在 Spring Boot 应用程序中申明如下的过滤器:

@Configuration public class MyConfiguration {

@Bean public FilterRegistrationBean corsFilter() {UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("http://domain1.com");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
    bean.setOrder(0); return bean;
}

}
三、spring 注解 @CrossOrigin 不起作用的起因
1、是 springMVC 的版本要在 4.2 或以上版本才反对 @CrossOrigin

2、非 @CrossOrigin 没有解决跨域申请问题,而是不正确的申请导致无奈失去预期的响应,导致浏览器端提醒跨域问题。

3、在 Controller 注解上方增加 @CrossOrigin 注解后,依然呈现跨域问题,解决方案之一就是:

在 @RequestMapping 注解中没有指定 Get、Post 形式,具体指定后,问题解决。

相似代码如下:

@CrossOrigin
@RestController public class person{


@RequestMapping(method = RequestMethod.GET) public String add() { // 若干代码

}
}
四、参考文章:
1、官网文档 https://spring.io/blog/2015/0…

2、http://fanshuyao.iteye.com/bl…

2、https://blog.csdn.net/taiyang…

3、https://blog.csdn.net/snowin1…

退出移动版