一、浏览器跨域问题产生
1、跨源资源共享(CORS)中文文档:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
2、什么是浏览器跨域问题
指的是浏览器不能执行其他网站的脚本。JavaScript出于安全方面的考虑,不允许跨域调用其他页面的对象,即同源策略。就好比我已经登录A网页,A网页上已经存储的cookie信息,B网页不能打开,B网页不能请求A网页的资源,除非这两个网页"同源"。同源意思是两个网页协议相同、域名相同、端口相同。
3、同源策略
同源策略是指:协议相同、域名相同、端口相同都要相同,只要一个不同就会产生跨域问题。
例子:
已有URL:http://www.example.com/hhb/index.html ,与以下URL同源情况:
①、http://www.example.com/hhb/manager.html
同源(同一域名下),可访问
②、https://www.example.com/hhb/index.html
不同源(协议不同https),不可访问
③、http://examle.com/hhb/index.html
不同源(域名不同),不可访问
④、http://www.example.com:81/index.html
不同源(端口号不同),不可访问
同源策略目的
同源策略的目的是为了保证用户信息的安全。防止恶意的网站盗取数据。Web应用程序只能从加载应用程序的同一个域请求HTTP资源,除非响应报文包含了正确CORS响应头。
二、跨域流程
1、示例登录请求(login)
这个我们实现跨域登录请求时,产生了两次login请求!
2、预检请求,OPTIONS
在发送真实请求前,会发送一个预检请求,检查请求的服务器是否允许跨域!
3、服务器响应允许跨域
服务器如果设置了允许跨域,服务器会在预检请求的响应头中添加允许跨域的信息!(这里我服务器已经编写了跨域配置)
跨域信息解释: (1)Access-Control-Allow-Credentials: true 跨域请求默认不包含cookie,设置为true可以包含cookie (2)Access-Control-Allow-Headers: content-type, token 跨域请求暴露的字段 注意:CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。 (3)Access-Control-Allow-Methods: POST 支持哪些方法跨域 (4)Access-Control-Allow-Origin: http://localhost:8001 支持哪些来源的请求跨域 (5)Access-Control-Max-Age: 表明该响应的有效时间为多少秒。在有效时间内,浏览器无需为同一请求再次发起预检请求。注意,浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将不会生效。
4、发送真实请求
这时会发送真实的登录login请求,包含自己的登录的用户密码等信息!
5、响应数据
服务器成功的响应数据,本次跨域成功!
三、跨域解决方法
1、第一种:使用nginx部署为同一域(理念,这里没有具体实现)
例如A请求服务器B,A和B不在同一域下。可以使用nginx反向代理需要请求的服务器B,使A和nginx服务器在同一域下。A直接请求ngnix代理服务器就可以了,由nginx服务器转发到具体的服务器B。
2、第二种:配置当前请求允许跨域(服务器端配置过滤器)
这里创建的是springboot项目,在主启动类同级目录下创建一个config目录,在config目录下编写我们的跨域配置类GuLiCorsConfiguration,对所有的请求进行过滤!
目录截图:
具体代码:
@Configuration
public class GuLiCorsConfiguration {
@Bean
public CorsWebFilter corsWebFilter(){
//springboot自带的跨域过滤器所需要的跨域配置源
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
//跨域配置源需要的具体配置
CorsConfiguration corsConfiguration = new CorsConfiguration();
//配置跨域
corsConfiguration.addAllowedHeader("*");
//支持哪些方法跨域
corsConfiguration.addAllowedMethod("*");
//支持哪些来源的请求跨域
corsConfiguration.addAllowedOrigin("*");
//允许携带cookie跨域
corsConfiguration.setAllowCredentials(true);
//对所有路径/**执行corsConfiguration配置
corsConfigurationSource.registerCorsConfiguration("/**",corsConfiguration);
return new CorsWebFilter(corsConfigurationSource);
}
}
3、第三种:配置当前请求允许跨域(服务器端配置WebMvcConfigurer)
这里创建的是springboot项目,在主启动类同级目录下创建一个config目录,在config目录下编写我们的跨域配置类CorsConfig,对所有的请求进行跨域映射!
目录结构:
具体代码:
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
// 设置允许跨域的路径
registry.addMapping("/**")
// 设置允许跨域请求的域名
.allowedOrigins("*")
// 是否允许证书
.allowCredentials(true)
// 设置允许的方法
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
// 设置允许的header属性
.allowedHeaders("*")
// 跨域允许时间
.maxAge(3600);
}
}