当先锋百科网

首页 1 2 3 4 5 6 7

一,为什么会出现跨域问题

跨域问题的产出,根本原因在于浏览器的同源策略 什么又是同源策略呢,官方解释:(同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。)

同源的定义:如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的

二,没有同源策略限制的隐患

  1. 可以跨域读取其他源cookie,获取用户登录信息;
  2. 钓鱼网站通过内勤iframe的方式来获取用户输入信息;

三,跨域正确的打开方式

    1,jsonp方式

1)ajax jsonp
2)   在HTML标签里,一些标签比如script、img这样的获取资源的标签是没有跨域限制的
示例前端代码:
<script src="https://www.pdf365.cn/api/getUserInfoApi?jsonpcallback=setUserInfo"></script>

 

示例后端代码

out.print(jsonp+"("+gson.toJson(user)+")");

out.flush();
out.close();
return;

缺点:只能是get请求,无法发送post请求

2,CORS

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)跨域资源共享 CORS 详解。这是处理跨域问题的标准做法。CORS有两种请求,简单请求和非简单请求。

只要同时满足以下两大条件,就属于简单请求。
(1) 请求方法是以下三种方法之一:

    • HEAD
    • GET
    • POST

(2)HTTP的头信息不超出以下几种字段:

    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
       

非简单请求(put/delete)会发出一次预检测请求,返回码是204,预检测通过才会真正发出请求,这才返回200。这里通过前端发请求的时候增加一个额外的headers来触发非简单请求。

"预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的;

具体使用方法:

前端按同源方式正常访问,使用ajax示例:

$.ajax({
url:'http://vip.foxitreader.cn/getUserInfoApi',
xhrFields: {
withCredentials: true //启用请求带cookie
},
success:function(data){
console.log(data);
}
});

 

服务端返回header中需要添加字段来满足cors

Access-Control-Allow-Origin  该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。如果需要跨域带cookie 改字段必须全匹配,不能是*,

                                                 包含Origin的请求不一定是跨域请求, 但是跨域请求一定包含Origin. 一些同源的请求同样也会包含Origin请求头.例如, Firefox浏览器不会在同源的请求中添加Origin, 但是Chrome和Safari会在同源的POST/PUT/DELETE请求中添加Origin请求头(但是同源的GET不会添加).

Access-Control-Allow-Credentials   可选,启用cookie

       Access-Control-Allow-Methods   该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。

       Access-Control-Allow-Headers   如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。

 

       Access-Control-Max-Age   该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。

 

服务的代码示例:

添加一个c'rosfilter 统一设置头部

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {

HttpServletResponse res = (HttpServletResponse) response;
HttpServletRequest req = (HttpServletRequest) request;
String origin =req.getHeader("Origin");
if(!StringUtils.isEmpty(origin)){
res.addHeader("Access-Control-Allow-Origin",origin);
}
String headers = req.getHeader("Access-Control-Request-Headers");
if(!StringUtils.isEmpty(headers)){
res.addHeader("Access-Control-Allow-Headers",headers);
}
res.addHeader("Access-Control-Allow-Methods","*");
res.addHeader("Access-Control-Max-Age","3600");
//enable cookie
res.addHeader("Access-Control-Allow-Credentials","true");
chain.doFilter(request, response);
}

3,代理

         使用nginx反向代理,解决跨域访问。

示例:

server_name  docer.test.foxitreader.cn;

location / {
root /home/ec2-user/git_src/docker365/web-html/dist;
try_files $uri $uri/ @rewrites;
}
location @rewrites {
rewrite ^(.*)$ /index/last;
}
location ^~ /webapi/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Nginx-Proxy true;
proxy_set_header Connection "";
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://52.83.93.136:20011/;
proxy_redirect default;

}