axios如何处理跨域问题
一、对同源和跨域的理解
以下摘取于
1、何为同源
同源是指域名,协议,端口三个都相同。下面的网站同源吗?
-
http://www.jianshu.com](https://www.jianshu.com) 和http://jianshu.com
不同源,因为域名不同
-
http://www.bilibili.tv>和http://www.bilibili.com
不同源,因为域名不同
-
http://localhost:3000> 和 http://localhost:3001
不同源,因为端口不同
-
http://qq.com> 和https://qq.com
不同源,因为协议不同
-
https://www.pixiv.net> 和 https://www.pixiv.net/manage/illusts/
同源,因为域名,协议,端口都相同
2、为何浏览器会制定同源策略
之所以有同源策略,其中一个重要原因就是对cookie的保护,只有同源网站的cookies才能共享。cookie 中存着sessionID 。黑客一旦获取了sessionID,并且在有效期内,就可以登录。当我们访问了一个恶意网站 如果没有同源策略 那么这个网站就能通过js 访问document.cookie 得到用户关于的各个网站的sessionID 其中可能有银行网站 等等。通过已经建立好的session连接进行攻击,比如CSRF攻击。
这里需要服务端配合再举个例子,现在我扮演坏人 我通过一个iframe 加载某宝的登录页面 等傻傻的用户登录我的网站的时候 我就把这个页面弹出 用户一看 阿里唉大公司 肯定安全 就屁颠屁颠的输入了密码 注意 如果没有同源策略 我这个恶意网站就能通过dom操作获取到用户输入的值 从而控制该账户所以同源策略是绝对必要的.
还有需要注意的是同源策略无法完全防御CSRF。
3、为何服务器端没有同源策略
在浏览器端发送的请求,会带上用户在对方网站的cookie,所以如果用户已登录,对方网站识别的身份是真正的处于登录状态用户。
在服务器端发送的请求,取不到用户在对方网站的cookie,所以对方网站识别的身份是未登录。
4、为何要研究跨域问题
因为受同源策略安全机制的影响(为了cookies),浏览器无法直接访问非同源的网站,但又必须得访问。怎么跨域访问?常用的方法有CORS,JSONP和iframe。
因为浏览器的同源策略规定某域下的客户端在没明确授权的情况下,不能读写另一个域的资源。而在实际开发中,前后端常常是相互分离的,并且前后端的项目部署也常常不在一个服务器内或者在一个服务器的不同端口下。前端想要获取后端的数据,就必须发起请求,如果不做一些处理,就会受到浏览器同源策略的约束。后端可以收到请求并返回数据,但是前端无法收到数据。
二、实验
通过axios检查输入框中输入的视频网址是否可以访问(实验时,该网址亲测可访问)
<!--视频连接-->
<div class="header">
<h2><strong>视频链接</strong></h2>
<input v-model="href" name="href" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp">
</div>
如果在vue中,用axios直接访问bilibili,会出现跨域问题
try{
_this = this;
axios.defaults.timeout = 2000;
alert(_this.href)
await axios.get(_this.href).then(res => {
_this.isVideoHref = res.data;
})
}catch (err){
console.log(err)
}
三、解决方案
网上说说可以让后台java php这些去请求api接口,然后返回给前台,多加一层转接可以处理CORS问题(我试了一下确实有效),也可以找代理
解决方法:
前台:
axios通过得到java后台返回的数据,判断该网址是否可以访问。如果可以,返回true,如果不可,返回false
//通过后台判断该网址是否可以访问
try{
_this = this;
axios.defaults.timeout = 2000;
await axios.get("/mheal/resource/UrlTest?url=" + this.href).then(res => {
_this.isVideoHref = res.data;
})
}catch (err){
console.log(err)
}
后台:
判断该网址是否可以访问
public class UrlUtils {
public static boolean testUrlWithTimeOut(String urlString,int timeOutMillSeconds){
long lo = System.currentTimeMillis();
URL url;
try {
url = new URL(urlString);
URLConnection co = url.openConnection();
co.setConnectTimeout(timeOutMillSeconds);
co.connect();
System.out.println("连接可用");
return true;
} catch (Exception e1) {
System.out.println("连接打不开!");
url = null;
return false;
}
}
}
axios可以通过controller得到链接访问的返回信息
//判断连接是否可访问
@GetMapping("/resource/UrlTest")
@ResponseBody
private Boolean isAccessible(HttpServletRequest request){
String url = request.getParameter("url");
//判断该链接是否有http,如果没有,则给该链接添加http网络协议
if(!url.contains("http")){
url = "http:" + url;
}
return UrlUtils.testUrlWithTimeOut(url,2000);
}
效果:
四、参考文档
1、彻底弄懂跨域问题
7、https://www.zhihu.com/question/31459669?sort=created