跨域请求及SpringBoot项目跨域配置

跨域请求问题及SpringBoot项目跨域配置

简介

什么是跨域请求

在 HTML 中,<a>, <form>, <img>, <script>, <iframe>, <link> 等标签以及 Ajax 都可以指向一个资源地址,而所谓的跨域请求就是指:当前发起请求的域与该请求指向的资源所在的域不一样。

协议 + 域名 + 端口号均相同,那么就是同域。

URL结果原因
http://store.company.com/dir2/other.html同源只有路径不同
http://store.company.com/dir/inner/another.html同源只有路径不同
https://store.company.com/secure.html失败协议不同
http://store.company.com:81/dir/etc.html失败端口不同 ( http:// 默认端口是80)
http://news.company.com/dir/other.html失败域名不同
跨域请求的隐患:CSRF 攻击

CSRF(Cross-site request forgery),跨站请求伪造。比如有两个网站,其中A网站是真实受信任的网站,而B网站是危险网站。在用户登陆了受信任的A网站是,本地会存储A网站相关的 Cookie,并且浏览器也维护这一个 Session 会话。这时,如果用户在没有登出A网站的情况下访问危险网站B,危险网站B模拟发出一个对A网站的请求(跨域请求),由于 Cookie 存在,危险网站就可以使用用户的身份的对A网站进行操作,而在A网站的角度来看是并不知道请求是由B网站发出来的(Session和Cookie均为A网站的)。

因而 CSRF 攻击可以简单理解为:攻击者盗用了你的身份,以你的名义发送请求。

针对 CSRF 的安全策略:同源策略

同源策略(Same-origin Policy)是 Netscape 提出的一个著名的安全策略,是浏览器最核心最基础的安全策略,现在所有的可支持 Javascript 的浏览器都会使用这个策略。

具体的同源策略

  • DOM 层面的同源策略:限制了来自不同源的”Document”对象或 JS 脚本,对当前“document”对象的读取或设置某些属性
  • Cookie 和 XMLHttprequest 层面的同源策略:禁止 Ajax 直接发起跨域HTTP请求(其实可以发送请求,结果被浏览器拦截,不展示),同时 Ajax 请求不能携带与本网站不同源的 Cookie。
  • 同源策略的非绝对性:<script><img><iframe><link><video><audio>等带有 src 属性的标签可以从不同的域加载和执行资源。
  • 其他插件的同源策略:flash、java applet、silverlight、googlegears等浏览器加载的第三方插件也有各自的同源策略,只是这些同源策略不属于浏览器原生的同源策略,如果有漏洞则可能被黑客利用,从而留下XSS攻击的后患

网页 f12 打开开发者模式可以在 console 中看到被拒绝的跨域请求,比如:

在这里插入图片描述

跨域解决办法1:CORS

​ 跨源资源共享 Cross-Origin Resource Sharing(CORS) 是一个新的 W3C 标准,它新增的一组HTTP首部字段,允许服务端其声明哪些源站有权限访问哪些资源。换言之,它允许浏览器向声明了 CORS 的跨域服务器,发出 XMLHttpRequest 请求,从而克服 Ajax 只能同源使用的限制。

CORS 请求

CORS 请求是包含 Origin 首部的 HTTP 请求。(Origin 首部表明预检请求或实际请求的源站,值为源站 URI,不包含任何路径信息,只是服务器名称)

**对于 CORS 请求,浏览器必须首先使用 OPTIONS方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨源请求。服务器确认允许之后,才发起实际的 HTTP 请求。**在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。

CORS 请求失败会产生错误,但是为了安全,在JavaScript代码层面是无法获知到底具体是哪里出了问题。你只能查看浏览器的控制台以得知具体是哪里出现了错误。

预检请求

预检请求用于检查服务端是否允许跨域请求,预检请求会使用OPTIONS作为方法,并包含以下 header:

  • Access-Control-Request-Method:告知服务器实际请求的方法
  • Access-Control-Request-Headers:告知服务器实际请求将要携带的 Header

预检请求的重定向

大多数浏览器不支持针对于预检请求的重定向。如果一个预检请求发生了重定向,浏览器将报告错误。

HTTP 响应 Header

对于 CORS 请求的 HTTP 响应包含以下 Header,表明该服务器具体支持怎样的跨域请求:

  • Access-Control-Allow-Origin:允许访问该资源的外域 URI,可使用 “*” 表示允许所有域的请求;
  • Access-Control-Allow-Credentials:指定是否允许实际请求使用 credentials(身份凭证)
  • Access-Control-Allow-Methods:允许的方法
  • Access-Control-Allow-Headers:允许的 Header
  • Access-Control-Max-Age:预检请求的结果能缓存的时间(单位:秒)
  • Access-Control-Expost-Headers:服务器允许浏览器访问的 Header

因此,只要在服务端配置了相应的参数,CORS 请求就能顺利跨域访问了。

SpringBoot 配置跨域请求

CorsWebFilter

SpringBoot 中,可以在配置文件中配置一个 CorsWebFilter 的 Bean 来设置允许的跨域请求,来看这个类的构造函数:

public class CorsWebFilter implements WebFilter {
   public CorsWebFilter(CorsConfigurationSource configSource) {
      this(configSource, new DefaultCorsProcessor());
   }
CorsConfigurationSource

CorsWebFilter 构造函数中需要传入CorsConfigurationSource,该接口有一个实现类:UrlBasedCorsConfigurationSource,这个实现类根据 CorsConfiguration配置的属性,将这些规则映射到对应的路径上。

使用registerCorsConfiguration方法将路径与 CorsConfiguration 实例指定的配置相映射:

urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
CorsConfiguration

CorsConfiguration 类可以 setter 方法设置所有上面提到的关于 CORS 的 HTTP Response Header:

在这里插入图片描述

完整的配置

@Configuration
public class CorsConfig {

    @Bean
    public CorsWebFilter corsWebFilter() {
        UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource
                = new UrlBasedCorsConfigurationSource();

        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.setAllowCredentials(true);

        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsWebFilter(urlBasedCorsConfigurationSource);
    }
}

参考链接

https://blog.csdn.net/ppxin/article/details/94717173

https://www.jianshu.com/p/f880878c1398

https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值