您的当前位置:首页正文

前后端分离开发跨域问题总结

2024-11-28 来源:个人技术集锦

开发需求:
在使用vue uniapp springboot开发微信小程序过程中,也是采用了前后端分离的模式,前端页面及js部署在微信小程序中,后端接口部署在阿里云服务器中,当前端向后端发起请求的时候一定是不符合同源策略的,也就无法访问,就会需要解决跨域问题,实现前后交互。本文系统介绍了跨域问题为什么会出现,以及所有的处理方式。

一、什么是跨域访问

跨域访问,必须先了解一个名词:

同源策略是指在浏览器端出于安全考量,向服务端发起请求必须满足:协议相同、Host(ip)相同、端口相同的条件,否则访问将被禁止,不满足要求的访问也就被称为跨域访问。

虽然跨域访问被禁止之后,可以在一定程度上提高了应用的安全性,但也为开发带来了一定的麻烦。

二、解决跨域问题

下文是解决跨域问题两种方式:前端、后端,其中后端又包括的方法,用一种即可,无需全部配置使用。

1、Vue前端配置代理解决跨域

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': ''
                }
            }
        }
    }
}

2、SpringBoot后端配置解决跨域

2.1 跨域配置类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("*");

    }
}
2.2 Controller添加@CrossOrigin注解
@RestController
@RequestMapping("users/")
public class IndexController {

    @GetMapping
    @CrossOrigin
    public String users() {
        return "users";
    }
}
2.3 添加CORS过滤器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);
    }
}
2.4 使用SpringSecurity来解决跨域问题
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;
    }
  }

显示全文