前后端分离 跨域

前提提示:最近的项目中,采用了前后端分离的开发模式。前端通过fetch api访问后端rest api。其间很自然的就会出现跨域问题。

什么是跨域?

以下是脑补之后的一些理解。

CORS(Cross-origin request sharing)跨域资源共享,是一个w3c标准,它允许你向一个不同源服务发出XMLHttpRequest请求,从而克服ajax只能请求同源服务的限制。

浏览器出于安全考虑,实施的一种同源策略,对非同源访问会主动拦截掉。

同源是指具有相同的:url协议(eg:http,https)、域名(eg:google.com)、端口

在浏览器中,script、img、iframe、link(这些标签似乎都有src属性)等标签可以加载跨域资源,而不受同源限制。

那么如何处理跨域的请求呢?目前比较多做法是jsonp,nginx反向代理,cors本文主要介绍cors.

jsonp:通过可以跨域的script标签,这样请求就能跨域访问了,通过约定好回调,就能获得相关响应数据。缺点是只支持GET不支持POST等其它类型请求;

nginx代理:通过一个代理服务器,转发请求到后端服务。缺点是扩展性不好。开发,测试,预发布等几个环境切换都需要配置。

cors: 支持所有类型的http请求,在服务端设置即可。缺点是老的浏览器不兼容(IE6,7,8 没关系,这些老版本不要管了)

CORS基本过程:

在HttpServertResponse响应中添加响应头:

Access-Control-Allow-Origin:(必设)添加浏览器允许的域名,可设置*表示任何。(origin是你浏览器上的地址组成的)

Access-Control-Allow-Credentials:(可设)是否允许发送cookie。如果设置为true,客户端请求也要将withCredentials设为true;

Access-Control-Request-Method: 必须的,表示CORS上会使用到那些HTTP方法;

Access-Control-Request-Headers: 必须的,表示CORS上会有那些额外的的有信息;

SpringBoot支持cors

SpringBoot中已经很好的支持了cors

CorsFilter类提供了改功能,通过构造UrlBasedCorsConfigurationSource类相关配置

以下是基本的代码:

@Configuration

public classCorsConfig {

private CorsConfiguration buildConfig(){

CorsConfiguration corsConfiguration =newCorsConfiguration();

corsConfiguration.addAllowedOrigin("*");//允许任何域名

corsConfiguration.addAllowedHeader("*");//允许任何头

corsConfiguration.addAllowedMethod("*");//允许任何方法get,post..

returncorsConfiguration;

}

@Bean

public CorsFiltercors Filter(){

UrlBasedCorsConfigurationSource source =new UrlBasedCorsConfigurationSource();

source.registerCorsConfiguration("/**",buildConfig());

return newCorsFilter(source);

}}

至此,一个接受任何域的跨域请求就ok了。

跨域共享cookie

但是还未结束,对于权限验证,目前还是使用的基于session,cookie的验证,所以这种方案需要实现跨域共享cookie.(强烈不建议使用cookie),那么对于客户端的请求就需要额外加上几个参数。

对于跨域共享cookie,需要注意的是后端响应的response head里的 Access-Control-Allow-Origin不能是通配符,且不能配置多个,Access-Control-Allow-Credentials需要设置为true

对于Access-Control-Allow-Origin的限制,只能指定单一域名或使用req.getHeader("Origin")来获取每次请求的Origin。这样一来,你要另外写一个Filter。

客户端的设置:以jQuery为例需要在里面加入xhrFields: {withCredentials: true},crossDomain: true 

在这些修改做好后,访问后端接口,但是依然不能解决。排查了半天,是跨域请求之前都要执行一个OPTIONS请求,这个请求是一个预检测的服务,用于获知服务端能接受哪些请求方法,origin等信息。后端会在响应中返回一个cookie,在下一次请求时会带上这个cookie。就实现了基本的跨域cookie共享,后端也能正常获取到session。

这个请求可以特殊处理。

你可能感兴趣的:(前后端分离 跨域)