开发需求:
在使用vue uniapp springboot开发微信小程序过程中,也是采用了前后端分离的模式,前端页面及js部署在微信小程序中,后端接口部署在阿里云服务器中,当前端向后端发起请求的时候一定是不符合同源策略的,也就无法访问,就会需要解决跨域问题,实现前后交互。本文系统介绍了跨域问题为什么会出现,以及所有的处理方式。
跨域访问,必须先了解一个名词:
同源策略是指在浏览器端出于安全考量,向服务端发起请求必须满足:协议相同、Host(ip)相同、端口相同的条件,否则访问将被禁止,不满足要求的访问也就被称为跨域访问。
虽然跨域访问被禁止之后,可以在一定程度上提高了应用的安全性,但也为开发带来了一定的麻烦。
下文是解决跨域问题两种方式:前端、后端,其中后端又包括的方法,用一种即可,无需全部配置使用。
import axios from 'axios'
const request = axios.create({
baseURL: '/api', // 这里是全局统一加上了 '/api' 前缀,也就是说所有接口都会加上'/api'前缀在,其他位置写接口的时候就不要加 '/api'了,否则会出现两个'/api',类似 '/api/api/user'这样的报错,切记!!!
timeout: 5000
})
// request 拦截器 可以自请求发送前对请求做一些处理
// 比如统一加token,对请求参数统一加密
request.interceptors.request.use(config => {
config.headers['Content-Type'] = 'application/json;charset=utf-8';
// config.headers['token'] = user.token; // 设置请求头
return config
}, error => {
return Promise.reject(error)
});
// response 拦截器 可以在接口响应后统一处理结果
request.interceptors.response.use(
response => {
let res = response.data;
// 如果是返回的文件
if (response.config.responseType === 'blob') {
return res
}
// 兼容服务端返回的字符串数据
if (typeof res === 'string') {
res = res ? JSON.parse(res) : res
}
return res;
},
error => {
console.log('err' + error) // for debug
return Promise.reject(error)
}
)
export default request
vue.config.js
module.exports = {
devServer: {
host: 'localhost',
open: true, // 自动打开浏览器
// 代理配置表,在这里可以配置特定的请求代理到对应的API接口
proxy: {
'/api': { // 匹配所有以 '/api'开头的请求路径
target: 'http://localhost:8080', // 代理目标的基础路径
// secure: false, // 如果是https接口,需要配置这个参数
changeOrigin: true, // 支持跨域
pathRewrite: { // 重写路径: 去掉路径中开头的'/api'
'^/api': ''
}
}
}
}
}
CorsConfig
(常用)@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
.maxAge(3600)
.allowedHeaders("*");
}
}
@CrossOrigin
注解@RestController
@RequestMapping("users/")
public class IndexController {
@GetMapping
@CrossOrigin
public String users() {
return "users";
}
}
CorsFilter
(常用)新建配置类CorsFilterConfig,创建CorsFilter
过滤器,允许跨域
@Configuration
public class CorsConfig {
// 跨域请求处理
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//允许所有域名进行跨域调用
config.addAllowedOrigin("*");
// config.addAllowedOrigin("http://localhost:8080");
//允许所有请求头
config.addAllowedHeader("*");
//允许所有方法
config.addAllowedMethod("*");
// 为url添加映射路径
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and().cors().configurationSource(corsConfigurationSource())
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());//将csrf令牌存储在cookie中 允许cookie前端获取
}
CorsConfigurationSource corsConfigurationSource(){
CorsConfiguration config = new CorsConfiguration();
config.setAllowedHeaders(Arrays.asList("*"));
config.setAllowedMethods(Arrays.asList("*"));
config.setAllowedOrigins(Arrays.asList("*"));
config.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return source;
}
}