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

在这里插入图片描述

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

一、什么是跨域访问

跨域访问,必须先了解一个名词:同源策略

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

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

跨域,指的是浏览器不能执行其他网站的脚本,是浏览器对JavaScript施加的安全限制。

所谓同源是指:域名、协议、端口均相同,例子如下:

http://www.jumper.com/index.html 调用 http://www.jumper.com/server.PHP (非跨域)

http://www.jumper.com/index.html 调用 http://www.sun.com/server.php (主域名不同:jumper/sun,跨域)

http://abc.jumper.com/index.html 调用 http://def.jumper.com/server.php(子域名不同:abc/def,跨域)

http://www.jumper.com:8080/index.html调用 http://www.jumper.com:8081/server.php(端口不同:8080/8081,跨域)

http://www.jumper.com/index.html 调用 https://www.jumper.com/server.php(协议不同:http/https,跨域)

请注意:localhost 和127.0.0.1虽然都指向本机,但也属于跨域。

二、解决跨域问题

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

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

​ 在Vue中解决跨域问题比较简单,因为我们每次浏览器发送的请求中,URL的前半部分一定是相同的,比如http://localhost:8080/users与http://localhost:8080/login,我们就可以将他们相同的URL提取出来,封装到axios.defaults.baseURL中,这样我们在每次请求的时候,就可以将请求地址简写成“/users”这样,相当于是将URL头部进行了一个简单的封装。
request.js

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;
    }
  }

猜你喜欢

转载自blog.csdn.net/qq_51808107/article/details/131392845