资讯专栏INFORMATION COLUMN

如何处理前端js跨域问题-php

diabloneo / 2986人阅读

摘要:而之所以没有设置成功,是因为存在本地,但是每个都有一个,当你本地的中存在你当前访问的域时,才会被带过去,而我的文件是本地访问的,即,而的域是的,所以不行了。

前端程序使用extjs写,在本地测试,发送请求到服务器时,发现存在跨域的问题,cookie也没有set成功,于是乎在这里整理一下解决过程

由于篇幅较长,不想看解决过程的可以翻到最后看总结
1.跨域允许
2.客户端无法携带跨域cookie
3.因为加了withCredentials报文头,可是客户端不知道服务器允不允许报的错
4.由于客户端不知道服务端是否允许POST请求而报的错

假设我的服务器IP是120.111.111.123

# 本地的html
# index.html



    


    




#服务器的php文件
#path setcookie.php

点击“请求”按钮,发送请求后发现js报错

XMLHttpRequest cannot load http://120.111.111.123/setcookie.php. 
Response to preflight request doesn"t pass access control check: No "Access-Control-Allow-Origin" header is present on the requested resource. 
Origin "null" is therefore not allowed access.

报这个错就说明我们跨域了,不在允许的访问源,于是乎我在服务的setcookie.php加入header("Access-Control-Allow-Origin:*");允许所有源


然后又报错

XMLHttpRequest cannot load http://120.111.111.123/setcookie.php. Request header field X-Requested-With is not allowed by Access-Control-Allow-Headers in preflight response.

这次的报错是因为,在跨域的时候,extjs不会直接发post请求,而是先发送一个option请求,看看服务器允许什么访问头(比如是不是允许post请求),验证成功后才会发送真正的请求

#用谷歌的开发者工具抓的option报文
OPTIONS /setcookie.php HTTP/1.1
Host: 120.111.111.123
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: POST
Origin: null
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
Access-Control-Request-Headers: x-requested-with
Accept: */*
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8

接下来,我们只要发送我们允许什么请求头就行了

#path /setcookie.php

session_start();
header("Access-Control-Allow-Origin:*"); 

header("Access-Control-Allow-Methods:OPTIONS, GET, POST"); // 允许option,get,post请求
header("Access-Control-Allow-Headers:x-requested-with"); // 允许x-requested-with请求头
header("Access-Control-Max-Age:86400"); // 允许访问的有效期

// 功能...
// ...

继续测试我们的新功能,成功的解决了跨域问题


but,cookie没有“设置成功”。而之所以没有“设置成功”,是因为cookie存在本地,但是每个cookie都有一个domain,当你本地的cookie中存在你当前访问的域时,才会被带过去,而我的index.html文件是本地访问的,即http://localhost/index.html,而cookie的域是120.111.111.123的,所以不行了。于是乎继续改

#path index.html


    


    



继续访问,报错

XMLHttpRequest cannot load http://120.111.111.123/setcookie.php. 
Response to preflight request doesn"t pass access control check: A wildcard "*" cannot be used in the "Access-Control-Allow-Origin" header when the credentials flag is true. 
Origin "null" is therefore not allowed access. 
The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute.

现在这个错误产生的原因就是
1.因为加入了withCredentials之后,Access-Control-Allow-Origin就不能用“*”了,既然不允许访问这个源,那我就让你发个报文头让你允许访问呗!

好了,上传完代码,继续测试。发送请求之后,又报错了(这错中错,一个个坑搞的大家都看得不耐烦了吧,我保证,这是最后一个报错了)

XMLHttpRequest cannot load http://120.111.111.123/setcookie.php. 
Response to preflight request doesn"t pass access control check: Credentials flag is "true", but the "Access-Control-Allow-Credentials" header is "". 
It must be "true" to allow credentials. Origin "null" is therefore not allowed access.

大概的意思就是说我给你发了withCredentials报文头,但是你服务器没有跟我说允许我带这个报文头,那么解决方法就是加上允许发这个报文头的报文头

# path setcookie.php

接下来进行最终的测试,biu~成功了,终于成功了!!!(0.0自己嗨起来了)

接下来总结一下,之所以跨域会引起那么多问题,都是因为耿直的客户端,发什么类型的请求都要服务器允许,而且要明文允许,允许的内容包括如下
1.跨域允许
解决方法:服务器发送允许客户端发送源的报文头
header("Access-Control-Allow-Origin:".$_SERVER["HTTP_ORIGIN"]);

2.客户端无法携带跨域cookie
这个时候就可以在extjs中加入withCredentials

       Ext.Ajax.request({
            url: "http://120.111.111.123/setcookie.php",
            method: "POST",
            params: { 
                "text": "hello world"
            },
            withCredentials: true,
            success: function(transport){
                // do something
            },
            failure: function(transport){
                alert("Error: " - transport.responseText);
            }
        });

3.因为加了withCredentials报文头,可是客户端不知道服务器允不允许报的错(耿直的客户端)
这个时候就在服务器发送Access-Control-Allow-Credentials

header("Access-Control-Allow-Credentials:true");

4.由于客户端不知道服务端是否允许POST请求而报的错
这个时候要在服务器端加入

header("Access-Control-Allow-Methods:OPTIONS, GET, POST");
header("Access-Control-Allow-Headers:x-requested-with");
header("Access-Control-Max-Age:86400");

以上汇总起来就是

header("Access-Control-Allow-Methods:OPTIONS, GET, POST");
header("Access-Control-Allow-Headers:x-requested-with");
header("Access-Control-Max-Age:86400");  
header("Access-Control-Allow-Origin:".$_SERVER["HTTP_ORIGIN"]);
header("Access-Control-Allow-Credentials:true");
header("Access-Control-Allow-Methods:GET, POST, PUT, DELETE, OPTIONS");
header("Access-Control-Allow-Headers:x-requested-with,content-type");
header("Access-Control-Allow-Headers:Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With");

代码已经放到github了,有啥问题欢迎大家指出

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/22635.html

相关文章

  • 何处前端js跨域问题-php

    摘要:而之所以没有设置成功,是因为存在本地,但是每个都有一个,当你本地的中存在你当前访问的域时,才会被带过去,而我的文件是本地访问的,即,而的域是的,所以不行了。 前端程序使用extjs写,在本地测试,发送请求到服务器时,发现存在跨域的问题,cookie也没有set成功,于是乎在这里整理一下解决过程 由于篇幅较长,不想看解决过程的可以翻到最后看总结1.跨域允许2.客户端无法携带跨域cooki...

    yeyan1996 评论0 收藏0
  • 高级前端面试题大汇总(只有试题,没有答案)

    摘要:面试题来源于网络,看一下高级前端的面试题,可以知道自己和高级前端的差距。 面试题来源于网络,看一下高级前端的面试题,可以知道自己和高级前端的差距。有些面试题会重复。 使用过的koa2中间件 koa-body原理 介绍自己写过的中间件 有没有涉及到Cluster 介绍pm2 master挂了的话pm2怎么处理 如何和MySQL进行通信 React声明周期及自己的理解 如何...

    kviccn 评论0 收藏0
  • 2018大厂高级前端面试题汇总

    摘要:面试的公司分别是阿里网易滴滴今日头条有赞挖财沪江饿了么携程喜马拉雅兑吧微医寺库宝宝树海康威视蘑菇街酷家乐百分点和海风教育。 (关注福利,关注本公众号回复[资料]领取优质前端视频,包括Vue、React、Node源码和实战、面试指导) 本人于7-8月开始准备面试,过五关斩六将,最终抱得网易归,深深感受到高级前端面试的套路。以下是自己整理的面试题汇总,不敢藏私,统统贡献出来。 面试的公司分...

    zzir 评论0 收藏0

发表评论

0条评论

diabloneo

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<