Spring boot之前后端分离项目的跨域问题

220 阅读4分钟

1.前言

现在大多数互联网的网站项目都用到了Spring系列的框架,而随着技术革新,摒弃了传统的JSP/Servlet项目,新项目一般都会使用到前后端分离的准则。这样做的好处是通过将前端和后端项目的界限进行区分,从而提高开发效率,也便于项目的测试和运维。

而在前后端分离的项目中,无论是Spring boot还是Spring cloud项目,最常见也是最核心的问题就是跨域问题。因为前端和后端的项目都处在不同的服务器端口上,换句话来说就是项目的端口不共用,无法直接进行数据传输。这时就必须设置项目的跨域问题。

2.什么是跨域?

跨域是指浏览器不能执行其他网站的脚本。 它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。

[1]. 什么是同源策略?

同源策略是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

同源策略限制以下几种行为:

  • Cookie、LocalStorage 和 IndexDB 无法读取
  • DOM和JS对象无法获得
  • AJAX 请求不能发送

[2]. 常见的跨域场景

URL说明是否允许通信
www.domain.com/a.js www.domain.com/b.js www.domain.com/lab/c.js同一域名,不同文件或路径允许
www.domain.com:8000/a.js www.domain.com/b.js同一域名,不同端口不允许
www.domain.com/a.js www.domain.com/b.js同一域名,不同协议不允许
www.domain.com/a.js http://192.168.4.12/b.js域名和域名对应相同ip不允许
www.domain.com/a.js x.domain.com/b.js domain.com/c.js主域相同,子域不同不允许
www.domain1.com/a.js www.domain2.com/b.js不同域名不允许

3.跨域方式

跨域方式主要可以分为前端配置跨域和后端配置跨域,一般只用配置一个,也就是说前端配置了跨域后端就可以不用配置跨域。

[1].前端跨域

前端跨域可以参考慕课网的一篇文章:www.imooc.com/article/291…

而本篇博客主要是介绍如何在后端项目配置跨域。

[2].后端跨域

后端跨域一般分为两种:第一种是添加@CrossOrigin注解;第二种是配置项目的全局跨域。

添加@CrossOrigin注解

当使用的是Spring boot 1.x版本时,可以直接在controller层上添加@CrossOrigin,便可解决跨域问题。但在Spring boot 2.x版本之后就不再支持不带配置信息的@CrossOrigin注解,当还是使用@CrossOrigin时如下:

@CrossOrigin
@RestController
public class EntryController {
    @Autowired
    private UserService userService;
    ...
}

前端控制台或报错,如下:

image-20210318115320783.png

这时你便会配置@CrossOrigin注解如下:

@CrossOrigin(origins = "*",maxAge = 3600)
//@RestController的作用为@Controller+@ResponseBody之和
@RestController
public class EntryController {
    @Autowired
    private UserService userService;
    ...
}

配置完后一定要重启项目,不然不会生效,之后一般不会报错了。

如果你按上述配置之后仍然报错,别急,这时你就应该检查你在后端是否配置了过滤器和拦截器,如果配置了,那此时就不能直接用 @CrossOrigin(origins = "*",maxAge = 3600)了(这时我在开发自己的项目时的血的教训)。这时便要在后端配置全局的跨域规则,如下。

配置全局跨域规则

在你的com.xxx.xxx下新建config目录,新建MyCorsConfig类(名字可任意取,最好不要和java中的类库重名),代码设置如下:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
//加上配置注解
@Configuration
public class MyCorsConfig {
        //加上@Bean放入Spring的IOC容器中
        @Bean
        public CorsFilter corsFilter() {
           //新建跨域配置
            CorsConfiguration corsConfiguration = new CorsConfiguration();
            //允许所有请求源(url)
            corsConfiguration.addAllowedOrigin("*");
            //允许所有请求头信息
            corsConfiguration.addAllowedHeader("*");
            //允许所有请求url中包含的方法名
            corsConfiguration.addAllowedMethod("*");
             //允许所有请求url中包含用户的凭证信息
            corsConfiguration.setAllowCredentials(true);
            //新建基于url的配置源信息
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            //将跨域规则注册进去(类似于List中的add方法)
            source.registerCorsConfiguration("/**", corsConfiguration);
            return new CorsFilter(source);
        }
}

注:配置了全局的跨域规则后就不用配置@CrossOrigin注解了。

按上述要求配置完毕后重新启动项目,就不会报错了。

4.总结

跨域问题在开发网页应用时会经常遇到,而在解决跨域问题时使用前端解决的话可选择项过多而找不到合适的方案,这时不如和后端开发小哥交流一下,直接在后端配置跨域就行了,简单又省事(狗头保护)。

如果你对此问题还有其他的解决方式或有疑问,欢迎评论留言!(本文和SegmentFault社区文章同步更新)