如果你从事 web 应用开发,在前端使用异步请求(/)时,那你或多或少都应该在浏览器控制台见识过如下异常信息。
是的,这就是在异步请求时跨域失败的异常信息。接下来本文将会先简单地介绍跨域的基础知识,再详细地介绍如何在 spring 应用中处理跨域。
跨域,全称为“跨域资源共享”(Cross-origin resource sharing),是浏览器的一种安全机制。只会在浏览器中,使用 AJAX (fetch/XMLHttpRequest)时发生。当你在一个 web 页面中,使用 ajax 对目标 URL 发起了请求,只要目标 URL 的 协议,主机,端口 和当前 web 页面的 协议,主机,端口 任意不一致,就会产生跨域。
例如,我在页面 中,对如下 URL 发起 AJAX 请求,都会导致跨域:
当浏览器发现当前请求存在跨域的时候,浏览器会先往目标 URL 发送一个预检请求()进行预检。这个请求会提交一些 Header 信息,服务器会根据此做出响应,同样也会写入一些 Header。浏览器就可以根据响应的 Header 信息来确认是否要阻止当前的跨域请求,也就是跨域成功与否。
理解跨域,本质上就是理解和跨域有关的请求 Header 和 响应 Header。
-
跨域请求,是从哪里发出,也就是表示请求来自哪个源(协议 + 主机 + 端口)。
-
跨域请求将会使用什么请求方法发起请求。
-
跨域请求将会提交哪些 Header 给服务器。
-
允许发起跨域请求的源,例如:,可以使用通配符: 表示允许所有。
-
允许跨域请求使用哪些请求方法,多个用逗号分割。
-
允许跨域请求提交哪些 Header,多个用逗号分割。
-
允许在跨域请求的响应中访问的额外的 Header 名称,多个的话,使用逗号分割。
默认情况下,在跨域请求的响应中,Javascript 的的只能访问 、、、、、 这个几个基本的响应头。如果你要访问其他的 Header,需要通过此设置。例如:。
-
缓存时间,可选,用来指定本次预检请求的有效期,单位为秒。在这个时间内,再次发起跨域请求不会再进行预检。
-
是否允许客户端携带凭证,boolean 值。如果设置为 ,那么客户端在发起跨域请求的时候会在请求中携带 Cookie 等凭证信息。
用通俗的语言来描述跨域预检的过程:浏览器发现 Javascript 正在发起一个跨域请求的时候,会先往这个URL发起一个预检()请求,告诉服务器“我打算给你发起一个请求,我所在的地址是 XXX,我要使用 XXX 请求方法,我还要提交 XXX 等 Header”。服务器收到后请求后,响应服务器“我只接受来自于 XXX 的跨域请求,只能用 XXX 请求方法,请求只能携带 XXX Header,请求可以携带凭证,还允许客户端读取响应的 XXX Header,并且30分钟内不必重复发起预检请求”
完成了这一轮协商后,浏览器就可以判断是否要继续发起真正的跨域请求。
一些要注意的点:
- 如果服务器要求客户端可以携带凭证 ,那么 不能设置为通配符 ,而是必须要设置完整的跨域请求源。
- 、、 都可以设置通配符 ,但是可能存在浏览器兼容问题,需要注意。
进阶阅读:
- MDN 官方对跨域的介绍
- 阮一峰老师对跨域的介绍
简单一点,可以通过覆写 中的 方法来配置应用的全局的跨域设置。
是全局配置,如果你需要更精准的控制 Api 的跨域策略,可以通过在 handler 方法或者是 controller 类上注解 来设置。
有了前面的理论支撑,你也不难看出这些注解属性所代表的含义,它可以注解在 Controller 类上,对当前类中的所有 hanlder 方法都生效,也可以注解在 handler 方法上,仅对此方法生效。如下:
不管是 配置还是 注解,都是用硬编码方式配置跨域,这相当的不够灵活。
Spring 提供了一个 的 实现类,可以让我们更加灵活地,以编程式的方式来配置跨域。这也是我较为推荐的一种方式。
上面的这个 是一个万能 Filter,基本上可以解决 spring 应用中 999.999% 的跨域问题。
注意:不论任何方式,如果将 设置为了 ,则 必须设置明确的源,不能使用通配符: ,否则运行时会抛出异常:
另外,上述三种方式,任选其一就行。不要重复定义!
创建一个简单的 spring boot(3.x)项目,在 端口的 端点提供一个 HTTP 服务,固定响应字符串:。
打开浏览器,访问 ,看到的是一个 404 错误页面,这是因为没有设置默认主页,这没关系。
我们可以在控制台用 Javascript 代码发起跨域请求,把服务器的响应输出到控制台。
如你所见,成功读取到了服务器的响应,跨域配置生效。
以前可以直接在浏览器控制台看到 请求,不知道从什么时候起,Chrome 不再在控制台展示 CORS 相关的 OPTIONS 预检请求。
那就用 工具模拟一个 请求吧,下面就是预检的请求/响应日志。
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/13708.html