本文目录一览:
1、同源策略与跨域问题解决
2、[Ajax 跨域问题及其解决方案](#Ajax 跨域问题及其解决方案)
3、java跨域怎么解决
4、java为什么会有跨域问题
同源策略与跨域问题解决
如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源。
举个例子:
下表给出了相对同源检测的示例:
由同源策略导致的的AJAX请求失败
例如:页面路径为:
后台接口地址为:
产生的结果:
此即为跨域请求失败
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了AJAX只能同源使用的限制。
在此之前,需要知道简单请求、复杂请求
简单请求:
某些请求不会触发 CORS 预检请求。本文称这样的请求为“简单请求”,请注意,该术语并不属于 Fetch(其中定义了 CORS)规范。若请求满足所有下述条件,则该请求可视为“简单请求”:
复杂请求:
与前述简单请求不同,“需预检的请求”要求必须首先使用 OPTIONS 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。"预检请求"的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。当请求满足下述任一条件时,即应首先发送预检请求:
若需要跨域,则需要在请求头里添加 Origin 字段
请求至后台若符合后台请求规则则可成功请求,并且后台会返回相应的规则
当请求为复杂请求时,浏览器会在请求前先发送一个 OPTIONS 请求
OPTIONS 是一个预检请求,与简单请求不同的是它会额外携带两个参数:Access-Control-Request-Method:该次请求的请求方式 Access-Control-Request-Headers:该次请求的自定义请求头字段
OPTIONS 发送至后台若后台成功响应,则继续发送复杂请求,若响应失败则不会发送复杂请求
继续发送复杂请求
(1)、OPTIONS不会携带body若后台方法上使用@RequestBody注解,则会报错:
例如:
此时需要在@RequestBody后添加参数required=false,允许body为空
即可解决该问题
(2)、OPTIONS请求不应被过多的发送,因为它也是一个http请求也会占用一部分资源,相应的一种解决方法
在响应中添加缓存字段,以减少OPTIONS请求
(1)、在Java web工程中加如下列过滤器即可
(2)、在nginx中配置
使用反向代理工具解决跨域问题:如 Nginx 、 node.js
以Nginx为例:
在Nginx的配置文件中加入:
启动Nginx再以
地址访问页面
访问后台接口
发现可正常请求
上述以
地址访问页面
访问后台接口
的方式遵循了,浏览器的同源策略自然不存在跨域
Nginx代理了页面请求和接口请求,所以页面请求和接口请求都在Nginx源内由Nginx去完成页面请求和接口的请求即:内
所以浏览器访问页面和接口都是以来进行访问的,满足了同源策略自然不存在跨域之说
图解:
跨域:
Nginx代理,满足同源策略
Nginx反向代理其实是一种欺骗浏览器的方法
[1] 浏览器同源政策及其规避方法
[2] XMLHttpRequest Level 2 使用指南
[3] 跨域资源共享 CORS 详解
[4] HTTP访问控制(CORS)
Ajax 跨域问题及其解决方案
主流的前后端分离模式下,当前端调用后台接口时,由于是在非同一个域下的请求,从而会引发浏览器的自我安全保护机制,最终结果是接口成功请求并响应,但前端不能正常处理该返回数据。 因此,当同时满足以下三个条件的情况下,就会出现跨域问题: 想要彻底解决跨域问题,只需要破坏以上三个条件的任一即可: 添加浏览器启动参数:chrome --disable-web-security,但是极不推荐这种解决方式。 Jsonp,全称 JSON with Padding,一种非官方的协议,而是一种约定;前端通过向后台发送 script 类型请求解决跨域,此时接口响应的 application/javascript 类型的数据会作为 callback 函数的参数进行处理。 所以,后台也需要做相应的处理。以 Java 为例,添加如下配置即可: 综上,jsonp 请求存在以下几个弊端: 用 Nginx 或 Apache 来代理调用方的请求(客户端变更为相对路径请求,而非绝对路径),此时对于浏览器来说,由于请求是同源的,因此就不存在跨域问题。 以 Java 应用为例,添加如下全局配置: 如果只想针对某个类下的接口,或者是某个具体的接口配置允许跨域,只需要在相应的地方添加注解 @CrossOrigin 即可。 如果配置了 nginx 作为代理服务器,那么只需要为 nginx 添加支持跨域请求即可: Q1:浏览器在执行跨域请求时,是先执行后判断,还是先判断后执行? A1:都有可能,这需要根据所发送的请求是简单请求还是非简单请求来判断;如果是非简单请求,浏览器每次在执行真正的请求之前,还会先发送一个 options 请求方式的预检命令【可设定缓存时长,取消每次请求都要预检,提高效率,参考上面的服务端配置】。关于两种请求的区分及定义,参考下图说明: Q2:如果是允许带(被调用方)cookie 的跨域请求,此时服务端同样配置为 Access-Control-Allow-Origin 等于 *,前端是否还可以请求成功? A2:不可以,此时要将 Access-Control-Allow-Origin 指定为调用方具体的域【可以先取得调用方的域再动态配置,这样就不存在多个域请求的限制问题】,并且添加配置 Access-Control-Allow-Credentials 为 true。
java跨域怎么解决
这个问题的回答很多的吧。。 一个是用jsonp的方式 另一种就是在java代码里接口那里加上
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
java为什么会有跨域问题
前言 相信大家在写前端脚本的时候经常会遇到发送数据到后台的情况,但是由于浏览器的限制,不同域名之间的数据是不能互相访问的,那前端怎么和后端如何进行数据之间的交换呢? JavaScript由于安全性方面的考虑,不允许页面跨域调用其他页面的对象,那么问题来了,什么是跨域问题? 答:这是由于浏览器同源策略的限制,现在所有支持JavaScript的浏览器都使用了这个策略。那么什么是同源呢?所谓的同源是指三个方面“相同”:
- 域名相同
- 协议相同
- 端口相同 下面就举几个例子来帮助更好的理解同源策略。 | URL | 说明 | 是否允许通信 | | --- | --- | --- | | 同一域名 | 允许 | | 不同域名 | 不允许 | | 同一域名不同端口 | 不允许 | | 同一域名不同协议 | 不允许 | 在JAVA中处理跨域问题,通常有以下两种常用的解决方法。 第一种解决方法 后台代码在被请求的Servlet中添加Header设置:
response.setHeader("Access-Control-Allow-Origin", "*");
PrintWriter out = null;
try {
out = response.getWriter();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.print("{'status':'ok'}");
out.flush();
out.close();
Access-Control-Allow-Origin这个Header在W3C标准里用来检查该跨域请求是否可以被通过,如果值为*则表明当前页面可以跨域访问。默认的情况下是不允许的。 在前端JS中需要向Servlet发出请求,请求代码如下所示:
$.ajax({
url: "your url",
type:"get or post",
dataType:"json",
data:{
....
},
success:function(data){
...
}
});
第二种解决方法 通过jsonp跨域请求的方式。JSONP和JSON虽然只有一个字母的区别,但是他们完全就是两回事,很多人很容易把他们搞混。JSON是一种数据交换的格式,而JSONP则是一种非官方跨域数据交互协议。 首先来说一下前端JS是怎么发送请求。代码如下所示:
$.ajax({
url:"your url",
type:"get or post",
async:false,
dataType : "jsonp",
//服务端用于接收callback调用的function名的参数
jsonp:"callbackparam",
//callback的function名称
jsonpCallback:"success_jsonpCallback",
success:function(data){
console.log(data);
},
error:function(data){
console.log(data);
}
});
这里的callbackparam和success_jsonpCallback可以理解为发送的data数据的键值对,可以自定义,但是callbackparam需要和后台约定好参数名称,因为后台需要获取到这个参数里面的值(即success_jsonpCallback)。 下面,最重要的来了,后台怎么样获取和返回数据呢。代码如下所示:
PrintWriter out = null;
String callback=req.getParameter("callbackparam");
String json=callback+"({'status':'ok'})";
try {
out = resp.getWriter();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
out.print(json);
out.flush();
out.close();
首先需要获取参数名为callbackparam的值,这里获取到的值就是“success_jsonpCallback”。然后将这个值加上一对小括号。小括号里放入你需要返回的数据内容,比如这里我返回一个JSON对象。当然你也可以返回其他对象,比如只返回一个字符串类型数据也可以。最后前端JS返回的数据就是这样的:
success_jsonpCallback({'status':'ok'})
浏览器会自动解析为json对象,这时候你只需要在success回调函数中直接用data.status就可以了。