前后端分离开发出现的跨域问题和解决方法
因为之前所在的公司开发模式前后端没有分离,所以在实际的开发中,基本上没有遇到跨域请求的问题,也没有注意相关问题。
问题描述
在前后端分离开发的时候,有的时候,在前端页面请求后台接口,控制到出现跨域错误,但是接口单独测试并无问题
解决方法
1. 前端处理
- 服务调用的时候进行跨域处理(修改请求接口的时候参数类型)
- 正常情况使用
ajax
调用服务的时候
$("#demo1").click(function(){
$.ajax({
url : 'http://www.tpadmin.top/Index/Test/crossDomain',
data : {},
type : 'get',
success : function (res) {
//No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1' is therefore not allowed access. 在执行时候报出的错误,这代表了跨域错误
alert(res);
}
});
});
- 使用
jsonp
的方式进行接口调用,但是此种方式仅限于GET
请求,并且存在过多的约束,一般不推荐
$("#demo2").click(function(){
$.ajax({
url : 'http://www.tpadmin.top/Index/Test/crossDomain',
data : {},
type : 'get',
dataType : 'jsonp',
success : function (res) {
alert(res);
}
});
});
- 使用反向代理的方式处理跨域问题
如果是vue-cli
的项目,在项目的根目录创建全局配置文件 vue.config.js
module.exports = {
// 基本路径
publicPath:"./", // 可以设置成相对路径,这样所有的资源都会被链接为相对路径,打出来的包可以被部署在任意路径
outputDir:"dist", //打包时生成的生产环境构建文件的目录
assetsDir: 'public', // 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录
devServer: {
//代理模式,用于解决接口跨域的问题
proxy: {
'/api': {
//target: 'http://localhost:8001/pm', // 对应自己的接口
target : 'http://114.55.164.189:8001/pm',
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': '',
},
},
},
}
}
2. 后端处理
- 如果是
springboot
的项目直接在Controller
类上面添加@CrossOrigin
注解jdk
版本要求是1.8以上.
/**
其它的控制层继承该类即可解决跨域问题
*/
@CrossOrigin
public class commonController {
}
- 采用拦截器的方法实现
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Autowired
private EnvConfig envConfig;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
boolean isTrue = envConfig.getIsDev();//判断是测试服才需要解决跨域问题
if (isTrue) {
response.addHeader("Access-Control-Allow-Origin", "*");
           response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
response.addHeader("Access-Control-Allow-Headers",
"Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,token");
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) throws Exception {
}
});
}
}
- 过滤器的方式进行过滤判断
@Configuration
public class GlobalCorsConfig {
/**
* 允许跨域调用的过滤器
*/
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//允许所有域名进行跨域调用
config.addAllowedOrigin("*");
//允许跨越发送cookie
config.setAllowCredentials(true);
//放行全部原始头信息
config.addAllowedHeader("*");
//允许所有请求方法跨域调用
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
- 全局配置器,进行全局配置
@Configuration
public class CorsMappingConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/dev/**")
.allowCredentials(true)
.allowedMethods("GET","PUT","DELETE","POST","OPTIONS")
.maxAge(3600);
}
}
3. Nginx介入的方式(类似于vue中的那个反向代理原理相同)
配置文件如下
server{
listen 8888;
server_name 192.168.1.100;
# 静态页面的
location /{
proxy_pass http://192.168.1.100:8080;
}
# api路由
location /api{
proxy_pass http://localhost:8001/api;
}
}