首页 > 其他分享 >跨域问题

跨域问题

时间:2024-02-19 10:55:06浏览次数:35  
标签:Control Access 浏览器 跨域 问题 服务器 请求

1,概念

跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。


跨域问题的产生是由于浏览器的同源策略。

同源策略(Same-Origin Policy)是一种浏览器安全策略,用于限制在浏览器中加载的网页脚本与来自不同源的资源进行交互。同源指的是协议(如 HTTP 或 HTTPS)、域名和端口号三者完全相同。

同源策略的目的是保护用户的信息安全,防止恶意网站通过跨域请求访问用户的数据。如果没有同源策略的限制,恶意网站可能会利用用户的浏览器发送跨域请求,获取用户的敏感信息。

同源策略涵盖了以下几个方面的限制:

  1. Cookie、LocalStorage 和 IndexedDB 等客户端存储的读取限制:脚本只能访问与其来源相同的存储区域,无法读取其他网站的数据。
  2. DOM 访问限制:脚本只能访问与其来源相同的 DOM 元素,无法直接操作其他网站的页面元素。
  3. XMLHttpRequest 和 Fetch API 的跨域请求限制:默认情况下,这些网络请求只能发送到与脚本来源相同的域名。
  4. 媒体数据的限制:音频和视频等多媒体资源的播放,受到了同源策略的限制。

有三个标签是允许跨域加载资源:

  1. <img src=XXX>
  2. <link href=XXX>
  3. <script src=XXX>

2,CORS

cross-origin resource sharing, 跨域资源共享。

CORS需要浏览器和服务器同时支持。目前,所有主流浏览器都支持该功能,IE浏览器不能低于IE10。在浏览器端, 整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,用户对这些都不会有感觉。因此,实现CORS通信的关键是服务器。

1,跨域请求分类

a. 请求方式为下列之一:
   GET
   POST
   HEAD
b. 请求头信息不超出以下字段:
   Accept
   Accept-Language
   Content-Language
   Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

凡是同时满足以上两个条件的, 就是简单请求.

2,简单请求

  对于简单请求, 浏览器直接发出CORS请求, 即浏览器自动在请求header中加上Origin字段, 告诉服务器这个请求来自哪个源(请求协议+域名+端口). 服务器收到请求后, 会对比这个字段, 如果字段值不在服务器的许可范围内, 服务器会返回一个正常的HTTP响应, 但是其响应头中不会包含Access-Control-Allow-Origin字段, 浏览器发现后, 就会抛出一个异常提示响应头中没有这个字段. 如果这个源在服务器的许可范围内, 服务器的响应头会加上以下字段:

  1. Access-Control-Allow-Origin:http://ip:port
    必需项, 值为请求头中的Origin的值.
  2. Access-Control-Allow-Credentials:true
    可选项, 值为boolean, 表示是否允许浏览器发送cookie, 需要在服务器配置.
  3. Access-Control-Expose-Headers:
    浏览器可以从跨域请求响应头中获取的字段值, 由服务器配置. 默认可以获取Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma这六个字段.

3,非简单请求

  对于非简单请求, 浏览器的CORS请求分为两步, 首先是执行预检(preflight)请求, 询问服务器是否允许当前源访问, 如果允许, 才会执行实际请求, 预检请求可以缓存(缓存时间由服务器定义), 在缓存有效期内再执行CORS请求时无需进行预检请求.

预检请求:

  • a. 预检请求的请求方式为OPTIONs, 表示这个请求是用来询问的。

  • b. 请求头信息包含以下字段:
    Origin: 请求源.

    • Access-Control-Request-Method: cors请求会用到的请求方式.
    • Access-Control-Request-Headers: cors请求会额外发送的请求头字段.
  • c. 服务器收到预检请求后会检查上面的三个字段值以确定是否允许跨域请求, 如果任意一项不完全满足则都不允许进行跨域请求.

  • d. 预检请求的响应中会包含如下字段:

    • Access-Control-Allow-Origin:
      必需项, 值为请求头中的Origin的值.
    • Access-Control-Allow-Credentials:
      可选项, 值为boolean, 表示是否允许浏览器发送cookie, 需要在服务器配置.
    • Access-Control-Allow-Headers:
      可选项, 允许跨域请求额外发送的header字段, 需要在服务器配置.
    • Access-Control-Allow-Methods:
      必需项, 允许跨域请求的请求方式.
    • Access-Control-Max-Age:
      必需项, 预检请求的缓存时间.

3,解决跨域的几种方法

1,JSONP

JSONP优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是仅支持 get 方法具有局限性,不安全可能会遭受 XSS 攻击。

原理就是使用 Script 标签不受同源策略的限制。

用不着,不研究。

2,Spring 的 @CrossOrigin

spring 框架提供 @CrossOrigin,可以用在方法上或者类上,默认允许所有请求和方法。

3,Spring 全局 CORS 配置

Spring:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
}

SpringBoot

@Configuration
public class MyConfiguration {
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**");
            }
        };
    }
}

可以修改任何属性:

@Override
public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/api/**")
        .allowedOrigins("http://domain2.com")
        .allowedMethods("PUT", "DELETE")
        .allowedHeaders("header1", "header2", "header3")
        .exposedHeaders("header1", "header2")
        .allowCredentials(false).maxAge(3600);
}

4,基于过滤器的 CorsFilter

作为上述其他方法的替代,Spring框架还提供了CorsFilter。在这种情况下,不用使用@CrossOrigin或WebMvcConfigurer#addCorsMappings(CorsRegistry)

@Bean
public FilterRegistrationBean corsFilter() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
    bean.setOrder(0);
    return bean;
}

5,Nginx 反向代理

原理也是 Cors。

server {
	listen 443 ssl;
	server_name   这里是域名;
  #定义跨域变量
	set $cors_origin "";
  #访问的域名与填写的域名比较
  if ($http_origin ~* "^这里填写调用我们系统的域名地址$") {
          set $cors_origin $http_origin;
  }
 //这里填*就是任何域名都允许跨域
  add_header Access-Control-Allow-Origin $cors_origin;
  #CORS请求默认不发送Cookie和HTTP认证信息。但是如果要把Cookie发到服务器,要服务器同意,指定 
  #Access-Control-Allow-Credentials字段。
	add_header Access-Control-Allow-Credentials 'true';
  #设置跨域请求允许的Header头信息字段,以逗号分隔的字符串
  add_header Access-Control-Allow-Headers 'Origin,X-Requested-With,Content-Type,Accept,Authorization,token';
  #设置跨域允许的请求
  add_header Access-Control-Allow-Metthods 'POST,GET,PUT,OPTIONS,DELETE';

  # 预检请求处理
  if ($request_method = OPTIONS) {
          return 204;
  }

"预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的,因此我们需要在Nginx配置中,针对预检请求进行处理,直接返回204 & Response Header,表示服务器支持允许跨源的访问。

4,CORS 不起作用原因排查

  1. 是springMVC的版本要在4.2或以上版本才支持@CrossOrigin

  2. 非@CrossOrigin没有解决跨域请求问题,而是不正确的请求导致无法得到预期的响应,导致浏览器端提示跨域问题。

  3. 在Controller注解上方添加@CrossOrigin注解后,仍然出现跨域问题,解决方案之一就是

  4. 对于非简单请求,Option 请求并不会携带所有请求头,如果后端有拦截器之类的验证,而没有跳过 OPTION 请求,导致验证失败返回,此时没有经过 @CrosOrigin 等,浏览器也会体现为跨域问题。

5,参考文献

Spring Cors:https://blog.csdn.net/qq_18671415/article/details/109275495
Cors:https://www.jianshu.com/p/f5a88983f42d

标签:Control,Access,浏览器,跨域,问题,服务器,请求
From: https://www.cnblogs.com/cnff/p/17797874.html

相关文章

  • redis高频问题--缓存--数据淘汰策略
    redis-数据淘汰策略redis具体的有八种淘汰策略数据淘汰策略建议总结问答......
  • redis高频问题--缓存--数据过期策略
    redis的数据过期策略惰性删除定期删除总结回答......
  • echarts自适应问题,echarts中怎么改变字体单位实现自适应
    参考文档:https://blog.csdn.net/MFWSCQ/article/details/102522944最初想着怎么给echarts设置vw单位或者rem,echart中怎么把legend的单位设置为vw或者rem来使表格自适应,后面发现行不通。项目中使用px-to-vw包,将所有px转为对应的vw,所有可以根据相同比例进行缩放,做到自适应效果。但......
  • 在家自己动手修电视解决屏幕跳动问题
    在家自己动手修电视解决屏幕跳动问题2024/2/18问题描述​ 电视(Skyworth)买的时间久了或长时间没有使用会出现屏幕跳动的问题,一会正常一会跳动并伴有黑线。解决步骤拆开后盖检查各连接线是否正常电视机大体都由这几个部分组成:逻辑板、排线、电源板……检查它们的链接是......
  • 跨域问题解决
    跨域举例A网站部署在localhost:63343请求loocalhost:8080/api/user/add,就会出现跨域问题。同源策略同源策略:协议,主机,端口,只有这三者全部相同时,才可以相互访问。现在接口地址为101.10.11.1X:8081,请判断以下哪些可以通过:访问地址描述结果https://127.0.0.1:808......
  • 如果由于大量数据插入数据库导致数据库性能持续下降问题?该如何进行性能优化?
    有些操作会使数据库的性能下降,MySQL是一种常用的关系型数据库管理系统,性能下降可能是由索引问题、查询语句问题、数据更新问题、锁竞争、配置参数问题、硬件资源问题或者慢查询等多种因素引起的。针对具体情况进行分析和优化可以提高MySQL的性能。本文主要介绍MySQL数据库当大量数......
  • Ubuntu20.04 问题+解决方案(不定期更新)
    问题1:Ubuntu20.04错误提醒:无法修正错误E:Unabletocorrectproblems,youhaveheldbrokenpackages.例如:解决方案:https://blog.csdn.net/weixin_44284939/article/details/122647791问题2:dpkg:errorprocessingpackage***(--configure)错误解决办法E:Sub-proce......
  • safari浏览器正则表达式兼容问题
    发现问题解决问题1、正则格式不对2、IOS,MAC不支持零宽断言 发现问题在开发过程中难免会使用正则表达式来匹配或替换一些文本(字符串),原本以为在不同的浏览器,正则表达式是一样的。然而在实际开发测试中却遇到了问题。一般正则表达式使用的谷歌浏览器,火狐浏览器都正常,而在safari浏......
  • 场景问题解决方法
    1.tomcatspringboot通过域名访问时直接跳到127.0.0.1的问题这种情况极可能是因为 server.xml配置问题导致,可以参考这篇文章tomcat设置http代理详细教程-知乎(zhihu.com)2.如何访问内网中所有的服务和站点要访问一个内网中所有的服务和站点(如内网的所有网站和数据库等),......
  • redis高频问题--缓存击穿
    缓存击穿互斥锁==分布式锁互斥锁多用于关于钱的业务,保持强一致性性能差一些,因为需要互相等待逻辑过期保证高可用性,注重于用户的体验......