GVKun编程网logo

【error】No 'Access-Control-Allow-Origin' 跨域问题(跨域请求origin为null)

9

针对【error】No'Access-Control-Allow-Origin'跨域问题和跨域请求origin为null这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展Access-Cont

针对【error】No 'Access-Control-Allow-Origin' 跨域问题跨域请求origin为null这两个问题,本篇文章进行了详细的解答,同时本文还将给你拓展Access-Control-Allow-Origin 与 Ajax 跨域、Access-Control-Allow-Origin 标头如何工作? - How does Access-Control-Allow-Origin header work?、Access-Control-Allow-Origin 跨域问题、Access-Control-Allow-Origin 跨域问题 SpringMVC解决 与 前端JS Webpack解决等相关知识,希望可以帮助到你。

本文目录一览:

【error】No 'Access-Control-Allow-Origin' 跨域问题(跨域请求origin为null)

【error】No 'Access-Control-Allow-Origin' 跨域问题(跨域请求origin为null)

ajax报错:

XMLHttpRequest cannot load http://...... No ''Access-Control-Allow-Origin'' header is present on the requested resource. Origin ''null'' is therefore not allowed access.


跨域问题处理方式:dataType:"jsonp"


------------补充-------------------------------------------------------------------------------------------------

详见:http://kb.cnblogs.com/page/139725/

摘录:

用JSON(JavaScript Object Notation)来传数据,靠JSONP(JSON with Padding)来跨域。

因为src中的url文件都是可以实现跨域,而且json是js原生支持的,所以把json封装到js文件中来实现跨域。为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。

Access-Control-Allow-Origin 与 Ajax 跨域

Access-Control-Allow-Origin 与 Ajax 跨域

问题

在某域名下使用 Ajax 向另一个域名下的页面请求数据,会遇到跨域问题。另一个域名必须在 response 中添加 Access-Control-Allow-Origin 的 header,才能让前者成功拿到数据。

这句话对吗?如果对,那么流程是什么样的?

跨域

怎样才能算跨域?协议,域名,端口都必须相同,才算在同一个域。

参考:

  • Are different ports on the same server considered cross-domain? (Ajax-wise) 
  • 同事李栋的博客:跨源资源共享

当跨域访问时,浏览器会发请求吗

这是真正困扰我们的问题,因为我们不清楚浏览器会怎么做。它会不会检查到你要请求的地址不是同一个域的,直接就禁止了呢?

我在 jsbin 上 做了一个试验 ,使用 Chrome 打开。当点击 “Run with Js” 时,控制台上会打出:

XMLHttpRequest cannot load http://google.com/. No ''Access-Control-Allow-Origin'' header is present on the requested resource. Origin ''http://run.jsbin.io'' is therefore not allowed access. 

但开发者工具的”Network” 栏并没有任何记录。它到底发请求了没?

我又使用 python -m SimpleHTTPServer 在本地创建了一个小服务器,然后把地址改成它,结果发现在 python 这边的确打印出请求来了,可见浏览器的确发出了请求。

Access-Control-Allow-Origin

现在该 Access-Control-Allow-Origin 出场了。只有当目标页面的 response 中,包含了 Access-Control-Allow-Origin 这个 header,并且它的值里有我们自己的域名时,浏览器才允许我们拿到它页面的数据进行下一步处理。如:

Access-Control-Allow-Origin: http://run.jsbin.io

如果它的值设为 * ,则表示谁都可以用:

Access-Control-Allow-Origin: *

没错,在产品环境中,没人会用 *

你可以阅读下面这篇文章了解更多,并可找到其中的”Run Sample” 链接,实际体验一下:

http://www.html5rocks.com/en/tutorials/cors/

public HttpResponseMessage Get(string fatherId)
{
	string str = JsonConvert.SerializeObject(GetAleCategorysByFid(fatherId), Formatting.Indented);           
	HttpResponseMessage result = new HttpResponseMessage { Content = new StringContent(str, Encoding.GetEncoding("UTF-8"), "application/json") };
	result.Headers.Add("Access-Control-Allow-Origin", "*");
	return result;
}

Access-Control-Allow-Origin 标头如何工作? - How does Access-Control-Allow-Origin header work?

Access-Control-Allow-Origin 标头如何工作? - How does Access-Control-Allow-Origin header work?

问题:

Apparently, I have completely misunderstood its semantics. 显然,我完全误解了它的语义。 I thought of something like this: 我想到了这样的事情:

  1. A client downloads javascript code MyCode.js from http://siteA - the origin . 客户端从 http://siteA- origin 下载 javascript 代码 MyCode.js。
  2. The response header of MyCode.js contains Access-Control-Allow-Origin: http://siteB , which I thought meant that MyCode.js was allowed to make cross-origin references to the site B. MyCode.js 的响应标头包含 Access-Control-Allow-Origin:http:// siteB ,我认为这意味着 MyCode.js 被允许对站点 B 进行跨域引用。
  3. The client triggers some functionality of MyCode.js, which in turn make requests to http://siteB, which should be fine, despite being cross-origin requests. 客户端触发了 MyCode.js 的某些功能,该功能继而向 http://siteB 发出了请求,尽管这是跨域请求,但仍然可以。

Well, I am wrong. 好吧,我错了。 It does not work like this at all. 它根本不像这样工作。 So, I have read Cross-origin resource sharing and attempted to read Cross-Origin Resource Sharing in w3c recommendation 因此,我阅读了跨域资源共享,并尝试阅读 w3c 建议中的跨域资源共享

One thing is sure - I still do not understand how am I supposed to use this header. 可以确定的一件事 - 我仍然不明白我应该如何使用此标头。

I have full control of both site A and site B. How do I enable the javascript code downloaded from the site A to access resources on the site B using this header? 我对站点 A 和站点 B 都拥有完全控制权。如何使用此标头使从站点 A 下载的 javascript 代码能够访问站点 B 上的资源?

PS 聚苯乙烯

I do not want to utilize JSONP. 我不想利用 JSONP。


解决方案:

参考一: https://stackoom.com/question/id4F/Access-Control-Allow-Origin 标头如何工作
参考二: https://oldbug.net/q/id4F/How-does-Access-Control-Allow-Origin-header-work

Access-Control-Allow-Origin 跨域问题

Access-Control-Allow-Origin 跨域问题

                          跨域配置逻辑说明

 

  1. 在 springboot 启动时,添加允许跨域的相关配置。
  2. 在 spring 收到请求后,会在跨域配置的列表中,匹配相应的 host 地址和 uri,如果存在相应的 host 地址和 uri,就在 response 中添加允许跨域的 header
    Access-Control-Allow-Origin:http://127.0.0.1:8080
  3. 当浏览器收到上面的 header 时,就会允许跨域请求
  4. Access-Control-Allow-Credentials 响应头表示,是否可以将对请求的响应暴露给页面。返回 true 则可以,其他值均不可以。

    https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Access-Control-Allow-Credential

Spring boot 配置代码:

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    
    public void addCorsMappings(CorsRegistry registry) {
      registry.addMapping("/task/rest/getUnReadMessageNumber")//允许跨域的uri
        .allowedOrigins("*")  //允许跨域的请求host
        .allowedMethods("GET", "POST")  //允许跨域的请求方式
        .allowedHeaders("*")           //允许跨域的header
        .allowCredentials(true)        //是否有资格把响应内容,暴露到页面 
        .maxAge(72000L);       //token时长
    }

}

允许跨域例子:

 

Access-Control-Allow-Origin 跨域问题 SpringMVC解决 与 前端JS Webpack解决

Access-Control-Allow-Origin 跨域问题 SpringMVC解决 与 前端JS Webpack解决

 

 

 

跨域问题 是针对ajax的一种限制

跨域:浏览器对于JS的同源策略的限制。

以下情况都属于跨域:

域名不同                       如: www.jd.com   www.taobao.com

域名相同,端口不同       如: www.taobao.com:8081  www.taobao.com:8082

二级域名不同               如: 3c.tmall.com   chaoshi.tmall.com 

http和https也属于跨域

 

解决跨域问题的方案

目前比较常用的跨域解决方案有3种:

  • Jsonp

    最早的解决方案,利用script标签可以跨域的原理实现。  限制:需要服务的支持 ;  只能发起GET请求

  • nginx反向代理

    思路是:利用nginx把跨域反向代理为不跨域,支持各种请求方式   缺点:需要在nginx进行额外配置,语义不清晰

  • CORS

    规范化的跨域请求解决方案,安全可靠。

    优势:在服务端进行控制是否允许跨域,可自定义规则 ;   支持各种请求方式

    缺点: 会产生额外的请求

 

*****因为我们将采用CORS的方式解决,故重点介绍一下它如何来处理!!!*****

   

    CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)

它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

  • 浏览器端:目前,所有浏览器都支持该功能(IE10以下不行)。整个CORS通信过程,都是浏览器自动完成,不需要用户参与

  • 服务端:CORS通信与AJAX没有任何差别,因此你不需要改变以前的业务逻辑。浏览器会在请求中携带一些头信息,我们需要以此判断是否允许其跨域,然后在响应头中加入一些信息即可。这一般通过过滤器完成即可。

 

浏览器会将ajax请求分为两类,其处理方案略有差异:简单请求、特殊请求

简单请求

只要同时满足以下两大条件,就属于简单请求。:

(1) 请求方法是以下三种方法之一:HEAD  GET  POST

(2)HTTP的头信息不超出以下几种字段: Accept  Accept-Language  Content-Language  Last-Event-ID  Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

当浏览器发现发起的ajax请求是简单请求时,会在请求头中携带一个字段:Origin

 

Origin中会指出当前请求属于哪个域(协议+域名+端口)。服务会根据这个值决定是否允许其跨域。

如果服务器允许跨域,需要在返回的响应头中携带下面信息:

Access-Control-Allow-Origin: http://yangw.com
Access-Control-Allow-Credentials: true
Content-Type: text/html; charset=utf-8

 

Access-Control-Allow-Origin:可接受的域,是一个具体域名或者*(代表任意域名)

Access-Control-Allow-Credentials:是否允许携带cookie,默认情况下,cors不会携带cookie,除非这个值是true

要想操作cookie,需要满足3个条件:

      服务的响应头中需要携带Access-Control-Allow-Credentials并且为true。

      浏览器发起ajax需要指定withCredentials 为true

      响应头中的Access-Control-Allow-Origin一定不能为*,必须是指定的域名

 

特殊请求

不符合简单请求的条件,会被浏览器判定为特殊请求,,例如请求方式为PUT

特殊请求会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。

浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

与简单请求相比,除了Origin以外,多了两个头:

 

Access-Control-Request-Method:  接下来会用到的请求方式,比如PUT

Access-Control-Request-Headers:  会额外用到的头信息

Access-Control-Max-Age:本次许可的有效时长,单位是秒,过期之前的ajax请求就无需再次进行预检了(让它默认,不用处理)

 

我们只要解决了复杂清醒,简单情形自然包含了!

解决方式1:后端JAVA

我们用Java框架SpringMVC实现: 由于我这里是一个Spring Cloud项目,故写了个过滤器放在了网关里面统一处理

 

解决方式2--只在前端webpack-dev-server

webpack配置中主要的参数说明

2.1 ‘/api’
捕获API的标志,如果API中有这个字符串,那么就开始匹配代理,
比如API请求/api/users, 会被代理到请求 http://www.baidu.com/api/users 。

2.2 target
代理的API地址,就是需要跨域的API地址。
地址可以是域名,如:http://www.baidu.com
也可以是IP地址:http://127.0.0.1:3000
如果是域名需要额外添加一个参数changeOrigin: true,否则会代理失败。

2.3 pathRewrite
路径重写,也就是说会修改最终请求的API路径。
比如访问的API路径:/api/users,
设置pathRewrite: {’^/api’ : ‘’},后,
最终代理访问的路径:http://www.baidu.com/users,
这个参数的目的是给代理命名后,在访问时把命名删除掉。

2.4 changeOrigin
这个参数可以让target参数是域名。

2.5 secure
secure: false,不检查安全问题。
设置后,可以接受运行在 HTTPS 上,可以使用无效证书的后端服务器

2.6 其他参数配置查看http-proxy-middleware文档
其他的配置参数等信息,可以查看这里:https://github.com/chimurai/h…

 

*********************以上两种解决方式任选其一均可**************

 

 

 关于环境,我还在hosts中配置了域名映射,使用了nginx帮我反向代理

可以参考我上一篇博文  https://www.cnblogs.com/yangw/p/11947752.html

 

关于【error】No 'Access-Control-Allow-Origin' 跨域问题跨域请求origin为null的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于Access-Control-Allow-Origin 与 Ajax 跨域、Access-Control-Allow-Origin 标头如何工作? - How does Access-Control-Allow-Origin header work?、Access-Control-Allow-Origin 跨域问题、Access-Control-Allow-Origin 跨域问题 SpringMVC解决 与 前端JS Webpack解决的相关知识,请在本站寻找。

本文标签: