浏览器为什么会产生跨域访问安全问题
浏览器的限制
浏览器为了安全考虑会限制不同域下的请求资源访问. 跨域的简单请求(这里还有非简单请求,是先做个options请求预校验,通过了才会真正请求)还是可以正常到达后台,后台也可以正常执行返回,但是浏览器就是给报,跨域安全错误.
跨域请求
如果请求里面,协议 域名 端口 任何一个不一样,都会被认为是跨域的请求.
XHR (XMLHttpRequest) 请求
主要就是因为发起的请求是这种类型的,也就是说,即使你协议,域名 端口都不一样,只要请求类型不是这种xhr的,就不会产生跨域问题.比如 直接用img,script标签或者其他形式请求同样的接口地址, 就不会有跨域问题.
针对三种原因的解决思路
浏览器限制
可以通过比较麻烦的设置,让浏览器不要限制跨域安全请求. 但是这种的比较麻烦而且不是正道.
启动浏览器的时候,带上参数,比如不要去双击chrome的图标启动.而且用命令行窗口如下启动
chrome --disable-web-security --user-data-dir=d:\tmp
XHR请求
可以使用jsonp的形式,将原先是xhr类型的请求修改为非xhr的请求来处理,jsonp是一种动态生产script脚本的形式来请求对应接口.所以不存在跨域的问题.但是也要修改后台代码,后台不能直接返回普通的纯数据格式文本,要返回可以被解析为script的内容. 浏览器F12观察,可以知道jsonp请求的类型是 script,并且自动给请求加上了callback参数. 后台就得想办法判断如果参数里有callback的话,就给返回的数据,包装一层,让他变成js代码.
类似这样:请求指定callback=tmpfunction , 那么后台返回给前台的文本就要是 "tmpfunction(原先的返回纯数据内容文本)" 并且如果使用jquery的话,会临时生成一个脚本区域,来容纳这个方法.并且使用完后,立马被清理掉.
Jsonp 是利用script请求的,所以只支持get的方法了.弊端比较大
跨域
可以让接口方修改后台代码,通过配置允许跨域请求的源域名列表,来过滤一些白名单域的请求.但是这种的比较局限接口必须是我们可控制的. 还可以修改调用方的代码,或者http服务器配置信息,使用代理的方法,让xhr的请求,请求自己本域下的某个地址,然后转发到请求接口.然后将返回的结果,转手倒给调用方.
比如参考
https://www.cnblogs.com/ddlove/p/9945988.html
https://blog.csdn.net/supramolecular/article/details/84234129
虽然但是
虽然这么多,但是大部分场景就是把下面的代码拿走,加到一个filter里,基本可以解决掉了就。
public class CrosFilter implements Filter
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 (!org.springframework.util.StringUtils.isEmpty(origin)) {
//带cookie的时候,origin必须是全匹配,不能使用*
res.addHeader("Access-Control-Allow-Origin", origin);
}
res.addHeader("Access-Control-Allow-Methods", "*");
String headers = req.getHeader("Access-Control-Request-Headers");
// 支持所有自定义头
if (!org.springframework.util.StringUtils.isEmpty(headers)) {
res.addHeader("Access-Control-Allow-Headers", headers);
}
res.addHeader("Access-Control-Max-Age", "3600");
// enable cookie
res.addHeader("Access-Control-Allow-Credentials", "true");
chain.doFilter(request, response);
}
网友评论