文章目录
前言
作为前后端分离的项目,跨域问题是无法避免的,在开发中,通常我们都会在后端进行全局跨域的处理,今天向大家介绍几种跨域问题的解决方法。
一、CORS是什么?
CORS即跨源资源共享,它定义了一种浏览器和服务器交互的方式来确定是否允许跨域请求。它是一个妥协,有更大的灵活性,但比起简单地允许所有这些的要求来说更加安全。但是CORS也具有一定的风险性,比如请求中只能说明来自于一个特定的域但不能验证是否可信,而且也容易被第三方入侵。 这里一般需要后端配合,开启cors。
二、解决方法
1.后端解决方法
1.1.注解(局部跨域)
后台服务端添加注解**@CrossOrigin**,但是重复代码过多,而且维护麻烦,不推荐使用
@RestController
@RequestMapping("/user")
@CrossOrigin(origins = "*")
public class AdminUserController {}
1.2.返回新的 CorsFilter(全局跨域)
在任意配置类,返回一个 新的 CorsFIlter Bean ,并添加映射路径和具体的CORS配置路径。
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter() {
//1. 添加 CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//放行哪些原始域
config.addAllowedOrigin("*");
//是否发送 Cookie
config.setAllowCredentials(true);
//放行哪些请求方式
config.addAllowedMethod("*");
//放行哪些原始请求头部信息
config.addAllowedHeader("*");
//暴露哪些头部信息
config.addExposedHeader("*");
//2. 添加映射路径
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/**",config);
//3. 返回新的CorsFilter
return new CorsFilter(corsConfigurationSource);
}
}
在filter中的preHandle进行预处理
@WebFilter(filterName = "CorsFilter")
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "*");
chain.doFilter(req, res);
}
}
1.3. 重写 WebMvcConfigurer(全局跨域)
CrossConfiguration
@Configuration
public class CorsConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("*")
.allowedMethods("*")
.allowedOrigins("*")
.allowCredentials(true)
.maxAge(3600);
}
}
1.4 手动设置响应头(局部跨域)
使用 HttpServletResponse 对象添加响应头(Access-Control-Allow-Origin)来授权原始域,这里 Origin的值也可以设置为 “*”,表示全部放行。
@GetMapping("/index")
public String index(HttpServletResponse response) {
response.addHeader("Access-Allow-Control-Origin","*");
return "index";
}
1.5 使用自定义filter实现跨域
编写一个过滤器
@WebFilter(filterName = "CorsFilter")
public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "*");
chain.doFilter(req, res);
}
}
2.前端解决方法
2.1. vue.config.js配置项
使用vue-cli创建的vue 项目
vue3版本之后处理跨域问题需要在package.json的同级目录下创建vue.config.js文件,
编写相关的跨域配置
module.exports = {
configureWebpack: {
resolve: {
//文件别名
alias: {
api: '@/api',
assets: '@/assets',
components: '@/components',
layouts: '@/layouts',
router: '@/router',
store: '@/store',
utils: '@/utils',
views: '@/views'
}
}
},
devServer: {
//端口
port: 8081,
//后端接口
proxy: {
'/api': {
target: 'http://localhost:8099', // 目标代理接口地址
changeOrigin: true, // 开启代理,在本地创建一个虚拟服务端
// ws: true, // 是否启用websockets
pathRewrite: {
'^/api': ''
}
}
}
}
}
因为在vue.config.js文件之中配置的代理路径是api,所以我们在封装的axios请求中需要将baseURL设置为相同的**/api**
封装的axios请求js如下
//配置axios
import axios from 'axios'
const instance = axios.create({
baseURL: '/api',
timeout: 6000
})
export default instance
在请求接口文件中引用即可实现跨域
上面配置中,我们根据实际情况只需要修改proxyTable对于配置即可。
假设我后端请求地址是http://localhost:8090,所有api的接口url都以/api开头。所以首先需要匹配所有以/api开头的.然后修改target的地址为http://localhost:8090。最后修改pathRewrite地址。将前缀 ‘^api’ 转为 ‘/api’。如果本身的接口地址就有 ‘/api’ 这种通用前缀,
就可以把 pathRewrite 删掉。注意这个方式只能在开发环境中使用。
3.服务器解决方法
3.1.Nginx
在nginx的配置文件nginx.conf中进行配置
将根目录指向build之后的dist文件夹
配置和前端类似的接口转发
server {
listen 80;
server_name localhost;
root /usr/web/dist/;#"绝对路径(dist文件夹)"
location / {
root $root
index index.html
}
location /api {#api映射
add_header 'Access-Contro-Allow-Origin' '*';
proxy_pass https://www.csdn.net/;
}
}
总结
理解跨域的问题产生的本质就是代理,就不难解决这个问题了
以上三种方法是最常见,也是最有效的解决跨域的方法
后续会持续更新!