当前位置: 首页 > 资讯 > >正文

跨越障碍:实现数据互通-跨域方案

来源:知行谈架构    时间:2023-03-31 11:01:23

相信大部分前后端分离的项目中,都会经常碰到跨域的问题,刚开始写程序时,对这个也是很好奇,是为什么呢?随着对应用程序请求的原理了解的加深,可以总结出多种方式来解决这个问题。

什么是跨域


(资料图片仅供参考)

首先要了解下浏览器的同源策略,同源通常是指以下三个相同:

协议相同(如http,https)域名相同(二级域名与主域名也不是同一个域名)端口相同(同一个域名,不同端口也算不同)

如 http://example.com 与 https://example.com =>不同

http://a.example.com 与 http://b.example.com =>不同

http://example.com:8000 与 http://example.com:8001 =>不同

同源策略是浏览器为了保证用户的信息安全,防止其他恶意网站来窃取数据,最常见的是web 系统中的cookie,而这些cookie通常是保存了比较多的用户信息,如登录状态,用户信息等,如果其他网站可以任意去使用这些数据,那对于应用本身也是一种安全漏洞。

正因为有同源策略的限制,非同源的应用,是不能互相读取 cookie、LocalStorage、Dom、Ajax 请求不能发送。但是在现在微服务盛行的年代,前后端分离的架构下,跨应用之间的访问是很常见的,要如何解决这种情况呢?

CORS即跨域资源共享,是W3C的标准,一种基于http 协议请求头的机制,需要浏览器与服务器的支持,整个过程是浏览器与服务器自动完成。

浏览器根据请求的内容,将请求分成两种请求:简单请求、非简单请求

对于请求方法为HAED、GET、POST的请求,如果它的请求头是 Accept、Accept-Language 或者请求头是 Content-Type 并且内容是 application/x-www-form-urlencoded、multipart/form-data、text/plain, 满足以上的即为简单请求,其他的即为非简单请求。

一些简单请求可能会包含以上的内容之外的内容,比较常见的就是cookie,需要增加规范外的用户凭证相关的内容,Http规范里,需要服务器返回 Access-Control-Allow-Credentials: true,这样客户端才可以提交cookie上去。

非简单请求是对服务器的特殊请求,如PUT、DELETE或者是 content-type 为 application/json,非简单请求会发起一个预检请求,询问服务器当前所有的域名是否在服务器允许的范围,同时也会返回服务器允许的http请求方法和请求头字段。

预检请求会发起 OPTIONS的请求,来询问服务器,在请求头里,主要是用Origin 来标识来源,除此之外还有两个字段:

Access-Control-Request-Methods 标识当前用到的HTTP MethodAccess-Control-Request-Headers 标识当前请求会使用的请求头,比如自定义请求头字段的x-req-id

服务端响应预检的请求内容包括几个字段

Access-Control-Allow-Origin 允许哪些源来请求当前的服务器Access-Control-Allow-Methods 允许请求的HTTP方法Access-Control-Allow-Headers 允许请求的请求头Access-Control-Allow-Credentials Access-Control-Max-Age 指定当前预检请求的有效期,单位秒

服务器如果对于来源的Origin、Access-Control-Request-Methods、Access-Control-Request-Headers 的内容检测通过,则会将响应的字段返回给以上的字段中,浏览器会比较响应的字段来判断是否允许发起请求。

实践

静态页面

测试跨域

服务端启动 SpringBoot项目

点击Test后,会产生以下的内容

依据前面介绍的,只要增加Access-Control-Allow-Origin 即可,在SpringBoot里可以通过几种方式

直接增加 @CrossOrigin(origins = "http://localhost")

@Controllerpublic class CorsController {@CrossOrigin(origins = "http://localhost")@ResponseBody@RequestMapping(value = "/api/test")public String test() {return "cors hello";}}

配置 WebMvcConfigurer

@Configurationpublic class WebConfigure implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**").allowedOrigins("http://localhost").allowedMethods("GET", "PUT", "POST", "DELETE").maxAge(1800);}}

可以配置CorsFilter,声明成Bean

@Beanpublic CorsFilter corsFilter() {CorsConfiguration configuration = new CorsConfiguration();configuration.addAllowedOrigin("http://localhost");configuration.addAllowedHeader("*");// 逗号隔开configuration.addAllowedMethod("GET,POST,PUT,DELETE");UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", configuration);return new CorsFilter(urlBasedCorsConfigurationSource);}

以上都是通过程序上进行配置,可以通过网关或是Nginx进行统一配置

add_header Access-Control-Allow-Origin *;add_header Access-Control-Allow-Headers X-Requested-With,X-Req-id;add_header Access-Control-Allow-Methods GET,POST,OPTIONS;

通过以上的配置后,都可以等到如下的正常响应

总结

跨域是浏览器的行为,需要客户端与服务器两者进行确认建议按需配置允许的来源,不建议配置成 *

X 关闭

推荐内容

最近更新

Copyright ©  2015-2022 华东五金网版权所有  备案号:京ICP备2022016840号-41   联系邮箱:2 913 236 @qq.com