前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot跨域配置

SpringBoot跨域配置

作者头像
小沐沐吖
发布2022-09-22 15:29:12
1.1K0
发布2022-09-22 15:29:12
举报
文章被收录于专栏:小沐沐吖小沐沐吖

SpringBoot跨域配置

什么是跨域

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

例如:a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。注意:跨域限制访问,其实是浏览器的限制。理解这一点很重要!!!

同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域;

同源策略
同源策略

一、同源策略

  1. 同源,就是咱们域名、端口号、ip、采用的协议都相同,那么我们就是同源的
  2. 反之就是不同源的!!!
  3. 出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
  4. 所以,用最简单的话来说,就是前端可以发请求给服务器,服务器也可以进行响应,只是因为浏览器会对请求头进行判断,所以要么前端设置请求头,要么后端设置请求头

不同源的应用场景:

  1. 本地文件,向远程服务器发送请求,可以发送,但是会出现跨域
  2. 本地服务器跑前端文件,服务器跑服务器程序,也会出现跨域问题

二、跨域问题

axios发起的POST请求

代码语言:javascript
复制
Access to XMLHttpRequest at 'http://localhost:8080/login' from origin 'http://localhost:8081' 
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' 
header is present on the requested resource.

// 在'http://localhost:8080/login'从原点'http://localhost:8081'已被CORS策略阻止:
// 请求的资源上不存在“Access Control Allow Origin”标头

POST http://localhost:8080/login net::ERR_FAILED 200

Uncaught (in promise) AxiosError 
{
    message: 'Network Error', 
    name: 'AxiosError', 
    code: 'ERR_NETWORK', 
    config: {…}, 
    request: XMLHttpRequest,
    ......
}

三、后端解决CORS跨域

对于 CORS的跨域请求,主要有以下几种方式可供选择:

  1. 返回新的CorsFilter
  2. 重写WebMvcConfigurer
  3. 使用注解@CrossOrigin
  4. 手动设置响应头 (HttpServletResponse)
  5. 自定webfilter实现跨域

注意:

  • CorFilterWebMvConfigurer@CrossOrigin需要SpringMVC 4.2以上版本才支持,对应springBoot 1.3版本以上
  • 上面前两种方式属于全局 CORS 配置,后两种属于局部 CORS配置。
  • 如果使用了局部跨域是会覆盖全局跨域的规则,所以可以通过@CrossOrigin 注解来进行细粒度更高的跨域资源控制。
  • 其实无论哪种方案,最终目的都是修改响应头,向响应头中添加浏览器所要求的数据,进而实现跨域

所有解决跨域问题,不外乎就是解决浏览器拦截问题,要么前端设置请求头,要么后端设置请求头,无论谁设置请求头,浏览器只要放行即可

四、全局跨域

1、配置新的CorsFilter

代码语言:javascript
复制
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 GlobalCorsConfig {

    @Bean
    public CorsFilter corsFilter(){
        //1. 添加 CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        //放行哪些原始域
        // springboot 2.4.0 之前使用这个 或直接指定放行的域名http://localhost:8081...
        // config.addAllowedOrigin("*"); 
        config.addAllowedOriginPattern("*"); // springboot 2.4.0 之后使用这个
        // 是否发送 Cookie
        config.setAllowCredentials(true);
        // 放行哪些请求方式
        config.addAllowedMethod("*");
        // 放行哪些原始请求头部信息
        config.addAllowedHeader("*");
        // 暴露哪些头部信息
        config.addExposedHeader("*");
        //2. 添加映射路径
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**",config);
        //3. 返回新的CorsFilter
        return new CorsFilter(source);
    }
}

2、重写WebMvcConfigurer

代码语言:javascript
复制
import org.jetbrains.annotations.NotNull;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class GlobalCorsConfig implements WebMvcConfigurer{
    @Override
    public void addCorsMappings(@NotNull CorsRegistry registry) {
        registry.addMapping("/**")
                // 是否发送cookie
                .allowCredentials(true)
                // 放行哪些域名
                // springboot 2.4.0 之前使用这个 或直接指定放行的域名http://localhost:8081...
                // .allowedOrigins("*")
                .allowedOriginPatterns("*") // springboot 2.4.0 之后使用这个
                // 允许任何方法
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                // 允许任何请求头
                .allowedHeaders("*")
                .exposedHeaders("*")
                // 表明在3600秒内,不需要再发送预检验请求
                .maxAge(3600L)
        ;
    }
}

五、局部跨域

1、注解

在springboot2.x版本以后,点开注解源码可以看到credentials默认是关闭的,该值是一个布尔值,表示是否允许发送 Cookie 。默认情况下, Cookie 不包括在 CORS 请求之中,设置为 true,即表示服务器明确许可, Cookie 可以包含中跨域请求中,一起发送给服务器。这个值也只能设置为 true ,如果服务器不要浏览器发送 Cookie,删除该字段即可。 在1.x版本的springboot中,是以origins作为参数,而新版本则改为了originPatterns 在控制器(类上)上使用注解 @CrossOrigin:,表示该类的所有方法允许跨域

代码语言:javascript
复制
@RestController
@CrossOrigin(originPatterns = "*",allowCredentials = "true")
public class LoginController {
    ...
}

在方法上使用注解 @CrossOrigin:

代码语言:javascript
复制
@ApiOperation(value = "登录")
@PostMapping("login")
@CrossOrigin(originPatterns = "*",allowCredentials = "true")
public RespBean login(@RequestBody LoginVo loginVo, HttpServletRequest request){
    if (!CaptchaUtil.ver(loginVo.getCode(),request)){
        return RespBean.loginCode();
    }
    CaptchaUtil.clear(request);
    return loginService.login(loginVo.getUsername(), loginVo.getPassword());
}

2、手动设置响应头

控制器

代码语言:javascript
复制
@ApiOperation(value = "登录")
@PostMapping("login")
public RespBean login(HttpServletRequest request,HttpServletResponse response){
    // 调用cors工具类
    CorsUtilks.cors(request,response);
    ...
    return loginService.login(loginVo.getUsername(), loginVo.getPassword());
}

Cors工具类

代码语言:javascript
复制
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 手动设置响应头
 */
public class CorsUtilks {
    public static void cors(HttpServletRequest request, HttpServletResponse response){
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); // 设置允许所有跨域访问
        response.setHeader("Access-Control-Allow-Methods", "POST,GET,PUT,OPTIONS,DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With,Content-Type,Accept,Authorization,token");
        response.setHeader("Access-Control-Allow-Credentials", "true");
    }
}

六、自定义filter

代码语言:javascript
复制
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 自定义filter实现跨域
 */
@Component
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); // 设置允许所有跨域访问
        response.setHeader("Access-Control-Allow-Methods", "POST,GET,PUT,OPTIONS,DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With,Content-Type,Accept,Authorization,token");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void init(FilterConfig filterConfig){}

    @Override
    public void destroy() {}
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022 年 08 月,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SpringBoot跨域配置
    • 什么是跨域
      • 一、同源策略
        • 二、跨域问题
          • 三、后端解决CORS跨域
            • 四、全局跨域
              • 1、配置新的CorsFilter
              • 2、重写WebMvcConfigurer
            • 五、局部跨域
              • 1、注解
              • 2、手动设置响应头
            • 六、自定义filter
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档