1.跨域访问

概念
HTTP 协议中的 Origin Header 存在于请求中,用于指明当前请求来自于哪个站点。

字段内容
Origin 仅仅包含站点信息,不包含任何路径信息。

语法

Origin: ""
Origin: "<schema>://<host>[:port]"
// 例如
Origin: "https://baidu.com"
// 错误示范,包含了路径信息
Origin: "https://baidu.com/"

应用
CORS
当我们的浏览器发出跨站请求时,行为正确的服务器会校验当前请求是不是来自被允许的站点。服务器就是通过 Origin 字段的值来进行的判断。

当服务器的配置出错时,比如配置成了 https://baidu.com/,则可能造成一些难以理解的问题。

比如有的浏览器(IE)能够请求成功,而有的浏览器却请求失败(Chrome)。这不是因为前一个浏览器行为正确,而是因为前一个浏览器发出请求时没有带上 Origin 而后一个浏览器带上了正确的 Origin。而在服务器端,因为没有 Origin Header,所以认为这不是一次 CORS 请求,所以没有进行 CORS 校验。这也反过来要求服务端强制请求带上 Origin Header,才能进一步保证服务器的安全性。

2. 为什么页面一定要加Origin源码分析

/*** 这里为支持的请求头,如果有自定义的header字段请自己添加*/private static final String ALLOWED_HEADERS = "X-Requested-With, Tenant-Id, Blade-Auth, Content-Type, Authorization, credential, X-XSRF-TOKEN, token, username, client";private static final String ALLOWED_METHODS = "GET,POST,PUT,DELETE,OPTIONS,HEAD";private static final String ALLOWED_ORIGIN = "*";private static final String ALLOWED_EXPOSE = "*";private static final String MAX_AGE = "18000L";/*** 跨域配置*/@Beanpublic WebFilter corsFilter() {return (ServerWebExchange ctx, WebFilterChain chain) -> {ServerHttpRequest request = ctx.getRequest();if (CorsUtils.isCorsRequest(request)) {ServerHttpResponse response = ctx.getResponse();HttpHeaders headers = response.getHeaders();headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);headers.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE);headers.add("Access-Control-Max-Age", MAX_AGE);headers.add("Access-Control-Allow-Credentials", "true");if (request.getMethod() == HttpMethod.OPTIONS) {response.setStatusCode(HttpStatus.OK);return Mono.empty();}}return chain.filter(ctx);};}

调用此方法会判断:

    public static boolean isCorsRequest(ServerHttpRequest request) {return request.getHeaders().get("Origin") != null;}

注意此方法通过gateway中对跨域访问进行处理

或者使用下面的方式也可以:

@Configuration // gateway
public class GulimallCorsConfiguration {@Bean // 添加过滤器public CorsWebFilter corsWebFilter(){// 基于url跨域,选择reactive包下的UrlBasedCorsConfigurationSource source=new UrlBasedCorsConfigurationSource();// 跨域配置信息CorsConfiguration corsConfiguration = new CorsConfiguration();// 允许跨域的头corsConfiguration.addAllowedHeader("*");// 允许跨域的请求方式corsConfiguration.addAllowedMethod("*");// 允许跨域的请求来源corsConfiguration.addAllowedOrigin("*");// 是否允许携带cookie跨域corsConfiguration.setAllowCredentials(true);// 任意url都要进行跨域配置source.registerCorsConfiguration("/**",corsConfiguration);return new CorsWebFilter(source);}
}
1.跨域解释
1.1 怎么知道我遇到了跨域问题
如果项目没做前后端分离,是不会有跨域问题的。前后端分离的项目中,前端调用后台服务时,报错 No 'Access-Control-Allow-Origin' header is present on the requested resource,你就是遇到了跨域问题。另外,前端调试墙裂推荐使用chrome,使用QQ浏览器遇到过跨域访问不了但是不报错的坑爹事件。1.2 为什么有跨域问题
浏览器的同源策略拒绝了我们的请求。 所谓同源是指,域名,协议,端口相同,浏览器执行一个脚本时同源的脚本才会被执行。如果非同源,那么在请求数据时,浏览器会在控制台中报上面的异常,提示拒绝访问。这是为了同一浏览器打开多个网站时,保护你的A网站登陆信息不被B网站拿去访问A网站,B网站登陆信息同理。1.3 怎么解决跨域问题
网上的文章对于解决跨域问题的介绍都很详细了。但对于使用Nginx解决跨域大多写的不太详细或者太详细以至于干扰因素太多,看了容易造成误解。这里做个总结。2.使用nginx解决跨域问题
2.1 先明确几个概念
首先明确一个概念,前端项目、后端项目、以及nginx,这就是三个server项目,他们只是互相之间交流数据;
三个项目都有自己的ip:port组合,哪怕你是在同一台服务器上启动这三个server,他们的port也是不可能有一样的;
所以,前端项目,不论访问nginx还是访问后端项目,都会产生跨域问题。
2.2 解决跨域问题
以下举例都是项目在同一台机器上,所以IP相同,只以端口区分前端项目(8081)、后端项目(8082)和nginx(8080)。2.2.1 方法1:在nginx中配置地址重写(或者转发也行)
访问地址以/video_resource开头的都会被这个模块捕获,转发到http://192.168.137.189:8082的后端项目上去。例如此时访问http://192.168.137.189:8080/video_resource/userList/engineer,就会转发到http://192.168.137.189:8082/userList/engineer。
访问地址以/js开头的也被这个模块捕获,转发到http://192.168.137.189:8082的前端项目上去。server
{listen       8080;location /resource {rewrite  ^/resource/?(.*)$ /$1 break;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass http://192.168.137.189:8082/; # 转发地址}location /js {rewrite  ^/js/?(.*)$ /$1 break;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass http://192.168.137.189:8081/; # 转发地址}
}
此时统一通过nginx访问前后端项目,通过/js标识转发到前端项目,通过/resource标识转发到后端项目。浏览器同源策略记录的就是http://192.168.137.189:8080/,浏览器也只访问这个nginx的8080地址,跨域问题也就得到了解决。2.2.2 方法2:nginx中添加允许跨域请求头
server
{listen       8080;add_header Access-Control-Allow-Origin *;add_header Access-Control-Allow-Headers X-Requested-With;add_header Access-Control-Allow-Methods GET,POST,OPTIONS;location /resource {rewrite  ^/resource/?(.*)$ /$1 break;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_pass http://192.168.137.189:8082/; # 转发地址}
}
这就和不用nginx,直接在后端项目中(tomcat或者自己写的服务端代码)配置允许跨域一样,只不过把允许跨域的配置放在nginx中,这个配置解决了前端项目访问nginx的跨域问题,而nginx访问后端项目不存在跨域问题(不是浏览器,没有同源策略限制)。此时nginx对于后端就相当于一个代理分发服务器。3.总结
浏览器的同源策略只记录他访问对象的ip和port,访问其他资源如果还是这个ip:port,就不存在跨域问题,如果不是这个ip:port,就用nginx讲这个ip:port转发到要访问的ip:port,让他仍然访问这个同源策略的ip:port。

3. 使用nginx设置跨域

Nginx配置(推荐)核心思想就是通过nginx或者其他反代工具,将本是跨域的接口地址代理到本地,再调用本地代理后的地址,即可解决跨域问题
参考: https://www.jianshu.com/p/1080014a234f

总结

  • 从gateway配置跨域固然方便,配置一次,其他所有请求都支持了,但是这样会或多或少影响系统的性能,深一层次想,这其实并不是服务端该做的事情
  • Nginx配置反代的模式,虽然看上去麻烦,需要每个地方都配置跨域,但是由于nginx的高性能,将API反向代理后,并不会有明显的损耗,同时也变相降低了服务端的压力。所以推荐使用Nginx或其他反代工具来解决跨域问题。

HTTP Headers 之 Origin跨域访问一定要加上这个header相关推荐

  1. 前后端分离开发时候遇到的跨域访问问题

    在前后端分离开发的时候,经常会遇到后端自己能调通接口,使用postman等测试工具访问也没有问题,但是在页面请求的时候会出现跨域访问问题: No 'Access-Control-Allow-Origi ...

  2. 解决cookie跨域访问

    v一.前言 随着项目模块越来越多,很多模块现在都是独立部署.模块之间的交流有时可能会通过cookie来完成.比如说门户和应用,分别部署在不同的机器或者web容器中,假如用户登陆之后会在浏览器客户端写入 ...

  3. 允许跨域访问_PHP设置多域名允许跨域访问

    php中文网最新课程 每日17点准时技术干货分享 针对 PHP 语言设置多域名允许跨域访问 服务器变量: 服务器变量存储在 $_SERVER 数组中,在这个数组中有一个特殊的键值:HTTP_ORIGI ...

  4. SpringMVC中的异步请求-跨域访问

    发送异步请求: <%@page pageEncoding="UTF-8" language="java" contentType="text/h ...

  5. 【JavaWeb】解决cookie跨域访问

    随着项目模块越来越多,很多模块现在都是独立部署.模块之间的交流有时可能会通过cookie来完成.比如说门户和应用,分别部署在不同的机器或者web容器中,假如用户登陆之后会在浏览器客户端写入cookie ...

  6. Jetty Cross Origin Filter解决jQuery Ajax跨域访问的方法

    当使用jQuery Ajax post请求时可能会遇到类似这样的错误提示 XMLHttpRequest cannot load http://xxxxxx. Origin http://xxxxxx ...

  7. js跨域访问,No 'Access-Control-Allow-Origin' header is present on the requested resource

    js跨域访问提示错误:XMLHttpRequest cannot load http://...... No 'Access-Control-Allow-Origin' header is prese ...

  8. SpringMVC+RestFul详细示例实战教程(实现跨域访问)

    一.理解 REST REST(Representational State Transfer),中文翻译叫"表述性状态转移".是 Roy Thomas Fielding 在他200 ...

  9. cors 前后端分离跨域问题_前后端分离之CORS跨域访问踩坑总结

    前言 前后端分离的开发模式越来越流行,目前绝大多数的公司与项目都采取这种方式来开发,它的好处是前端可以只专注于页面实现,而后端则主要负责接口开发,前后端分工明确,彼此职责分离,不再高度耦合,但是由于这 ...

最新文章

  1. 2019微生物组—宏基因组分析专题培训第三期
  2. 成功解决ImportError: Could not find 'msvcp140.dll'. TensorFlow requires that this DLL be installed in a
  3. w7怎么查看电脑配置_2020年之学习UI设计需要什么样的电脑配置?
  4. FLEX实例:GOOGLE地图.
  5. c++学习笔记之数组及vector
  6. 蒂姆·库克:给好人留的后门同时也是给坏人留的
  7. 联发科技嵌入式_英特尔联手联发科技重回移动5G征途,能否与高通抗衡?
  8. 逸出 java_【java】知识系谱-基础篇-线程-发布、逸出
  9. web中hasmoreelements_Web开发模式【Mode I 和Mode II的介绍、应用案例】
  10. MySQL 视图的基础操作(五)
  11. react-生命周期
  12. 阴阳师服务器维护更新,阴阳师服务器3月10日维护更新了什么 阴阳师服务器3月10日维护更新一览...
  13. 为什么 Netflix 这么强?网飞 CEO 哈斯廷斯跟陆奇摊牌了
  14. 数据库高并发解决方案(一)查询优化
  15. c51语言语句 指令集,MCU
  16. FFplay命令分析-vf
  17. python制作恶搞_Pycharm制作搞怪弹窗的实现代码
  18. axi_ddr_top
  19. Droopy v0.2 靶机渗透(drupal 7.3版本漏洞)
  20. 02 | 从神经元说起:结构篇

热门文章

  1. 编写程序,计算两个二维平面向量的和向量。
  2. 微信小程序开发实现图片滚动效果
  3. 视频、音乐播放器大家都听说过,那么图片播放器呢
  4. vs+qt使用过程中遇到的问题(一)
  5. Python中list去重的方法
  6. 计算机应用基础成绩单样板,陕西 : 西安08年7月计算机应用基础上机考核成绩单...
  7. 【英文文献】如何阅读英文文献
  8. 光影魔术手2014 v4.4.1.304 官方免费版
  9. html5 表格文档常用指令
  10. DF-TAR: A Deep Fusion Network for Citywide Traffic Accident Risk Prediction... 阅读笔记