SpringMvc CORS-跨域处理

StandsSpringBoot: 学习

介绍

同源"指的是"三个相同":

  1. 协议相同
  2. 域名相同
  3. 端口相同

同源策略的目的:是为了保证用户信息的安全,防止恶意的网站窃取数据。

限制:如果非同源,共有三种行为受到限制。

  1. CookieLocalStorageIndexDB无法读取。
  2. DOM无法获得。
  3. AJAX请求不能发送。

工作原理是添加新的HTTP headers来让服务器描述哪些源的请求可以访问该资源,对于可能对服务器造成不好影响的请求,规范规定浏览器需要先发送“预检”请求(也就是OPTION请求),在预检请求通过后再发送实际的请求,服务器还可以通知客户端是否应该随请求发送“凭据”(例如 Cookie 和 HTTP 身份验证)。

HTTP Header介绍

Request Header

  1. Origin:请求的源信息(协议 + 域名 + 端口)
  2. Access-Control-Request-Method:预检请求类型
  3. Access-Control-Request-Headers:额外发送的Header信息

Resonse Header

  1. Access-Control-Allow-Origin:服务器接受的源信息,“*”表示所有
  2. Access-Control-Allow-Methods:服务器支持的所有跨域请求类型,“*”表示所有
  3. Access-Control-Allow-Credentials:服务器是否接受Cookies和HTTP Authentication
  4. Access-Control-Expose-Headers:服务器暴露的额外的Header,“*”表示所有
  5. Access-Control-Max-Age:本次预检的有效期
  6. Access-Control-Allow-Credentials设置为true时Access-Control-Allow-Origin不能设置为“*”

@CrossOrigin属性介绍

origins和value

支持的源,origins和value都是相同的配置,互为别名,默认配置是“*”,表示服务器支持所有源的跨域请求,安全信息较低,最好根据实际情况设置对应的信息(协议 + 域名 + 端口)。

​​​​​​​originPatterns

同样表示支持的源,Spring 5.3 引入的属性,默认为空,与origins二选一,支持通配符的形式配置origins,比如https://*.domain1.com,该字段为list,也就是可以配置多个。

​​​​​​​allowedHeaders

允许跨域的请求头信息,默认为“*”表示允许所有的请求头,CORS默认支持的请求头为:Cache-Control、Content-Language、Expires、Last-Modified、Pragma,如果你需要携带其他的请求头需要设置该属性。

​​​​​​​exposedHeaders

服务器允许客户端访问的相应头,默认为空,表示只允许访问:Cache-Control、Content-Language、Expires、Last-Modified、Pragma,如果需要客户端访问其他的相应头需要设置该属性。

​​​​​​​methods

服务器允许的Http Request类型,默认是允许GET、POST、HEAD,根据项目需要自行设置。

​​​​​​​allowCredentials

浏览器是否需要把凭证(如:cookies、CSRF tokens)发送到服务器,默认是关闭的,因为该选项开启后会与配置的源建立高度信任的关系,并且还会暴露一些敏感信息,所以开启该选项时origin不允许设置为“*”。

​​​​​​​maxAge

“预检”结果的缓存时间,单位是秒,默认1800s,在缓存时间内同一请求不需要“预检”请求。

 code

@Component
public class CorsFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        // 不使用*,自动适配跨域域名,避免携带Cookie时失效
        String origin = request.getHeader("Origin");
        if(StringUtils.isNotBlank(origin)) {
            response.setHeader("Access-Control-Allow-Origin", origin);
        }

        // 自适应所有自定义头
        String headers = request.getHeader("Access-Control-Request-Headers");
        if(StringUtils.isNotBlank(headers)) {
            response.setHeader("Access-Control-Allow-Headers", headers);
            response.setHeader("Access-Control-Expose-Headers", headers);
        }

        // 允许跨域的请求方法类型
        response.setHeader("Access-Control-Allow-Methods", "*");
        // 预检命令(OPTIONS)缓存时间,单位:秒
        response.setHeader("Access-Control-Max-Age", "3600");
        // 明确许可客户端发送Cookie,不允许删除字段即可
        response.setHeader("Access-Control-Allow-Credentials", "true");

        chain.doFilter(request, response);
    }

   @Bean
    public FilterRegistrationBean registerFilter2() {
        
       FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>();
       bean.addUrlPatterns("/*");
       bean.setFilter(new CorsFilter());
    // 过滤顺序,从小到大依次过滤
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
        }
}

@Configuration
@Order(1)
public class MyCorsFilter {
    @Bean
    public CorsFilter corsFilter() {

        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOriginPattern("*");
        // 是否发送 Cookie
        config.setAllowCredentials(true);
        // 支持请求方式
        config.addAllowedMethod("*");
        // 允许的原始请求头部信息
        config.addAllowedHeader("*");
        // 暴露的头部信息
        config.addExposedHeader("*");
        config.setMaxAge(Duration.ofMinutes(30));

        // 2.添加地址映射
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**", config);
        // 3.返回 CorsFilter 对象
        return new CorsFilter(corsConfigurationSource);
    }
}
  • 10
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值