要了解跨域,先要说说同源策略。
同源策略是由 Netscape 公司提出的一个著名的安全策略,所有支持 JavaScript 的浏览器都会使用这个策略。
由于浏览器同源策略的限制,非同源下的请求,都会产生跨域问题,jsonp即是为了解决这个问题出现的一种简便解决方案。
同源策略即:同一协议,同一域名,同一端口号。当其中一个不满足时,我们的请求即会发生跨域问题。
一个系统访问另一个系统才会存在跨域,同系统访问不存在跨.
跨域原因说明 示例
域名不同 www.jd.com 与 www.taobao.com
域名相同,端口不同 www.jd.com:8080 与 www.jd.com:8081
二级域名不同 item.jd.com 与 miaosha.jd.com
www.baidu.wenku.com 与 www.baidu.tieba.com
跨域不一定会有跨域问题。
因为跨域问题是浏览器对于ajax请求的一种安全限制:一个页面发起的ajax请求,只能是于当前页同域名的路径,这能有效的阻止跨站攻击。
因此:跨域问题 是针对ajax请求的一种限制。只有发送ajax请求才会发生跨域问题。
JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。
核心思想:网页通过添加一个 // 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字 // 处理服务器返回回调函数的数据
JQuery ajax实现:
$.ajax({
url: 'http://www.test.com:8080/login',
type: 'get',
dataType: 'jsonp', // 请求方式为jsonp
jsonpCallback: "handleCallback", // 自定义回调函数名
data: {}
});
Vue.js 实现:
this.$http.jsonp('http://www.domain2.com:8080/login', {
params: {},
jsonp: 'handleCallback'
}).then((res) => {
console.log(res);
})
规范化的跨域请求解决方案,安全可靠。
优势:
- 在服务端进行控制是否允许跨域,可自定义规则
- 支持各种请求方式
缺点:
- 会产生额外的请求,要做询问
此方式是在部署前后端分离项目时最常使用的。具体看上一篇博客,有配置的详细介绍。
项目前端用的端口号是8081,后端用的是8080
编写一个CORS的跨域过滤器
package com.rk.pethome.basic.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter() {
//1.添加CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//1) 允许的域,不要写*,否则cookie就无法使用了
config.addAllowedOrigin("http://127.0.0.1:8081");
config.addAllowedOrigin("http://localhost:8081");
//2) 是否发送Cookie信息
config.setAllowCredentials(true);
//3) 允许的请求方式
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
// 4)允许的头信息
config.addAllowedHeader("*");
//2.添加映射路径,我们拦截一切请求
UrlBasedCorsConfigurationSource configSource = new
UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
//3.返回新的CorsFilter.
return new CorsFilter(configSource);
}
}
只需要修改允许前端的域就行,本项目前端端口使用的是8081
后端还有一种方案,给需要跨域访问的接口添加@CrossOrigin注解
此时前端调用接口方式如下:
//加载所有的部门列表
loadAllDepartments(){
this.$http.patch("http://localhost/department/loadAll").then((res => {
this.depts = res.data;
}));
},
如果是前端开发,多个项目之间有相互访问的情况(只能在vue的项目可以解决)。
1、在项目的config/index.js
proxyTable: {
'/api': { //所有通过/api的请求都会代理到下面http://localhost:8080
target: 'http://localhost:8080',
//允许跨域
changeOrigin: true,
//移除url里面的api /api/user/login 代理过来就行http://localhost:8080/user/login
pathRewrite: {
'^/api': ''
}
},
},
只需要修改后端项目端口,本项目后端端口使用的是8080
2、在main.js中加入全局访问配置 为了不改变原来的访问,或者不需要每一次访问后台都要加上api.
//配置axios的全局基本路径
axios.defaults.baseURL='/api'
配置完成后需要重启前端服务器才能生效。此方法类似于Nginx反向代理
此时前端调用接口,只需要接口名就行,如下
//加载所有的部门列表
loadAllDepartments(){
this.$http.patch("/department/loadAll").then((res => {
this.depts = res.data;
}));
},