什么是跨域问题同源策略核心后端配置方案SpringBootpython-flask Nginx配置方案
前言
现在开发基本上是前后端分离模式,跨域问题的处理似乎变得很自然。 可以在前端解决,可以在后端解决,也可以在Nginx上解决。 我也不太会做前端,所以我会从后端的角度总结自己到目前为止在开发过程中是如何处理跨域问题的。
跨域问题浏览器是基于安全考虑使用同源策略。
同源战略怎样才算是同源?
所有协议域名端口必须相同
第一个同源策略用于限制对Cookie的访问,允许访问设置为只有同源页面的页面的Cookie。
cookie的目的是让服务端知道是谁发送了这次请求。 如果服务端验证通过,将在响应标头中添加一个Set-Cookie字段,浏览器会在下次启动请求时自动将cookie添加到HTTP请求的标头字段cookie中,并且服务端希望该用户登录
例如,现在我正在访问a网站。 登录成功后,再访问Web站点。 如果没有同源政策的限制,Web站点可以利用浏览器自动将cookie附加到HTTP请求标头字段的cookie中,然后将请求发送到Web站点,假装我自己进行操作。 这就是crossiterequestforgery (封闭请求伪造)。
PS :即使有同构战略也不一定安全。 cookie是明文的,通过配置httpOnly以防止前端操作cookie,或配置secure以防止通过https加密通信传输并被监听等方式来保障安全。
目前的同源策略更受限制:
Cookie、LocalStorage和IndexDB会阻止DOM无法获取请求的响应,而不是无法跨域发送请求。 要求可以发送。 后端可以成功接收前端发送的数据,但浏览器会阻止从后端返回到前端的结果。 浏览器是为了防止后端返回非同源的请求。
酷睿是W3C标准,是解决域间问题的标准方法。 通过允许浏览器向交叉源服务发出XMLHttpRequest请求,克服了只能发送同源请求的限制。
CORS实现机制:
当浏览器启动域间HTTP请求时,浏览器会自动将当前资源的域添加到请求标头中名为Origin的Header中。
有三个选项卡可以在域之间加载资源。
img src=
link href=
脚本src=
跨域有两种请求:
简单的请求:
请求方法只有HEAD、GET、POST
要设置为活动的标头信息包括:接受、接受语言、内容语言、最后事件id、内容类型(应用程序/x-www
非简单请求:不能同时满足简单请求的两个条件
对于简单请求:
浏览器将Origin字段添加到请求标头信息中并指示源。 服务器返回的标头包括访问控制全局定向和定向,如果需要携带Cookie,则标头包括访问控制全局定向
访问控制- allow-origin 3360 XXX.XXX.XXX.XXX 3360 XXX 3358 www.Sina.com/:
访问控制- allow-credentials : true (小写! (服务器在返回头信息里设置
访问控制- allow-origin : * http://www.Sina.com/:
访问控制- allow-credentials : true
访问控制-全局-定向3360请求的定向(获取请求后填写) ) ) ) ) )。
true和*不能同时存在啊。 记住!
需要携带Cookie允许http://www.xxx.com跨域请求如果想匹配所有的Origin并且不带Cookie预验证请求如果想匹配所有的Origin并且不带Cookie不需要重新发送允许跨域请求的秒
dentials 设置允许Cookie 后端配置方案 SpringBootF1: 使用@CrossOrigin(“http://xxx.xxx.xxx.xxx:xx”)注解,略,每个都配太累了。
F2:CORS全局配置,实现WebMvcConfigurer接口
@Configurationpublic class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry){ registry.addMapping("/**") .allowedOriginPatterns("*") .allowedMethods("GET","HEAD","POST","PUT","DELETE","OPTIONS") .allowCredentials(true) .maxAge(3600) .allowedHeaders("*"); }}F3:拦截器实现
@Componentpublic class CorsFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletResponse res = (HttpServletResponse) response; res.addHeader("Access-Control-Allow-Credentials", "true"); res.addHeader("Access-Control-Allow-Origin", res.getHeader("Origin")); res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT"); res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN"); if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) { response.getWriter().println("ok"); return; } chain.doFilter(request, response); } @Override public void destroy() { } @Override public void init(FilterConfig filterConfig) throws ServletException { }} python-flask from flask import Flask,jsonifyfrom flask import request,send_filefrom flask_cors import CORSfrom flask import make_responsefrom flask_cors import cross_originapp = Flask(__name__)CORS(app,supports_credentials=True)result = Nonedef make_request(resp): resp = make_response(resp) resp.headers['Access-Control-Allow-Origin'] = 'http://xxx.xxx.xxx.xxx:8081' resp.headers['Access-Control-Allow-Methods'] = 'GET,POST' resp.headers['Access-Control-Allow-Headers'] = '*' resp.headers['Access-Control-Allow-Credentials'] = 'true' return resp@cross_origin(supports_credentials=True)@app.route('/hello',methods=['GET'])def hello_world(): return make_request(jsonify({'code':200,'data':'Hello World'}))if __name__ == '__main__': app.run(debug=True,host='0.0.0.0',port=5000)CORS(app,supports_credentials=True)、@cross_origin(supports_credentials=True)、def make_request(resp)三选一就行,和Java类似。
Nginx配置方案Nginx反向代理的思路,就是通过Nginx解析URL地址的时候进行判断,将请求转发的具体的服务器上。
server { listen 8081; server_name localhost; # 当前服务的域名location / { root /html/dist; index index.html index.htm; } location /api/ { proxy_pass 你的接口地址; #添加访问路径录为/api的代理配置 proxy_http_version 1.1; } }修改之后要reload