去年我在做一个项目,是关于标签打印的,它就是一个Windows程序,提供标签打印功能,由其它程序(包括网站)告诉它需要打印怎样的标签,它就出标签,这个“告诉它需要怎样的标签”的过程,是通过HTTP的Post请求实现的,我把这个程序做成一个Self-Host的小网站,接受来自各方面的HTTP请求,测试下来可行,我分别自己写了个HTTP客户端以及使用现成的Postman来测试,都没问题。
直到项目上线前,发现浏览器没办法成功发送打印请求,原因是:浏览器默认情况下不允许跨站的异步请求。这啥意思呢?比如我在访问A.com,这时候页面JavaScript要求我用异步(注意是异步,不是同步,同步就没有这个问题)请求B.com的一个地址,此时我的浏览器就拒绝了这个动作。之前我有点不理解为什么要拒绝,现在我算是明白了,你想,假如你已经登录了B.com,B.com是信任你的身份的,而A.com想利用你已经登录了B.com这个状态,神不知鬼不觉地用页面JS向B.com发送一个异步请求,获取到一些你的敏感资料,然后存到自己的服务器上来,这个会有安全性问题,所以浏览器是拒绝的,注意,拒绝的主角是浏览器,而不是B.com,这样也不难解释为什么我自己写小程序测试以及使用Postman测试都没问题。
那这个问题应该怎么解决呢?这就需要用到W3C的标准——CORS(Cross-Origin Resource Sharing),这是一项技术标准:https://www.w3.org/TR/cors/,也就是说,现在主流的浏览器应当都支持,太旧的浏览器就不好说了。浏览器把能否跨站异步请求这个决定权交给目标网站,即前面提到的B.com,B说可以就可以,B说不可以就不可以,B可以配置自己的判定规则,比如B说我只允许来自C.com的跨站异步请求,那么A.com仍然是被浏览器阻止的。那么,浏览器如何知道目标网站是否允许呢?其实是通过几个HTTP头的字段来判断的,之前提供的w3.org的那个连接有具体说明,这里就不展开了。
服务器端如何支持CORS,这个就参考各自的实现吧,自己查查手册,关键字为CORS,EASY。