Spring Boot(十二) 优雅的跨域请求

166 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情

大家好! 我是慕歌,一只想教你学习 Spring Boot的野生coder! 欢迎来到慕歌的 Sping boot系列教程,希望通过这个教程带大家搭建基础的 Spring Boot项目,该教程所有知识点均来源于本人的真实开发!

前言

在前一节的学习中,慕歌将自己长期使用的异常处理工具类交给了小伙伴们,相信认真看过前一篇内容的小伙伴们一定是收获颇丰。优雅的结果集返回,优雅的异常处理,两篇文章覆盖了90% 后端与前端的交互场景,续学会它们,就再也不用担心于前端数据交流不畅了!但是在真实的与前端交互中,可能还会出现其他问题,跨域问题,我相信是很多新手都会遇到的问题。那么这一节,慕歌就带大家从后端的角度,解析解决跨域问题!

引入:

跨域只会出现在spring boot web项目中,需要使用spring boot 的web 依赖。

        <!--   web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
		<!--  test-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

跨域:

那么跨域是怎麽产生的
出于浏览器的同源策略限制,同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
什么是跨域:
当我们通过两种不同的协议访问:当前访问 :www.test.com/而实际访问时使用了另一种协议就导致www.test.com/index.html产生了跨域

跨域解决:

服务端会发送两次请求,第一次会发送预检请求,用于探测请求是否跨域,我们需要在服务端允许跨域请求的发送。那么解决方案有哪些呢,这里推荐几种在spring boot中的配置:
注解配置:可在需要进行跨域请求的位置添加此注解,该请求就可允许被跨域访问。对于小的项目,接口数量少,或者是对跨域有特殊需求可选择该方式。

@CrossOrigin注解

nginx代理:

nginx服务器具有反向代理的功能,可通过配置nginx服务,让所有服务有nginx服务器代理,nginx服务器允许跨域请求访问,所有请求经过nginx后映射真实的请求,就能够解决跨域问题。配置如下,可根据自己的服务名,服务端口进行修改:

// proxy服务器
server {
    listen       81;
    server_name  www.domain1.com;
    location / {
        proxy_pass   http://www.domain2.com:8080;  #反向代理
        proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
        index  index.html index.htm;
 
        # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
        add_header Access-Control-Allow-Origin http://www.domain1.com;  #当前端只跨域不带cookie时,可为*
        add_header Access-Control-Allow-Credentials true;
        add_header Access-Control-Allow-Methods GET, POST, OPTIONS;
        add_header Access-Control-Allow-Headers *;
    }
}

后端配置:

spring boot集合了 spring mvc的接口,能够对请求进行处理分发,所以如果我们在请求的接口处进行配置,允许请求跨域请求,那么跨域问题也能得到解决。配置如下,不同的spring boot 版本接口可能有差异,根据直接的spring boot 版本进行配置:

//请求跨域
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowedMethods("GET","POST","PUT","HEAD","OPTIONS")
                .allowCredentials(true)
                .allowedHeaders("*")
                .maxAge(3600);
    }

spring boot同样支持注入跨域配置,进行自动配置,定义跨域请求类,通过跨域过滤器加入配置。

@Configuration
public class CretCorsConfiguration{

    /**
     * 允许跨域调用的过滤器
     */
    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        //允许所有域名进行跨域调用
        config.addAllowedOrigin("*");
        //允许跨越发送cookie
        config.setAllowCredentials(true);
        //放行全部原始头信息
        config.addAllowedHeader("*");
        //允许所有请求方法跨域调用
        config.addAllowedMethod("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsWebFilter(source);
    }
//    @Bean
//    public CorsWebFilter corsWebFilter() {
//        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//        // 配置跨域
//        CorsConfiguration corsConfiguration = new CorsConfiguration();
//        // 允许哪个请求头
//        corsConfiguration.addAllowedHeader("*");
//        // 允许哪个方法进行跨域
//        corsConfiguration.addAllowedMethod("*");
//        // 允许哪个请求来源进行跨域
////         corsConfiguration.addAllowedOrigin("*");
//        corsConfiguration.addAllowedOriginPattern("*");
//        // 是否允许携带cookie进行跨域
//        corsConfiguration.setAllowCredentials(true);
//
//        source.registerCorsConfiguration("/**",corsConfiguration);
//        return new CorsWebFilter(source);
//    }
}

结语

这一章的分享到这里就结束了,下一节中还将带来华为云短信服务的分享!
如果您觉得本文不错,欢迎点赞支持,您的关注是我坚持的动力!