跨域携带身份凭证

跨域携带身份凭证

场景需求分析

在前后端分离的情况下,假如异步请求的域名与当前页面所在域名不相同,也就是不同源的情况下,鉴于同源策略,会禁止向异源发起请求。这种情况下可通过跨域请求解决上述问题,而在跨域请求时,有些情况下会要求携带上身份凭证(例如cookie),下面就针对这一需求来详细解答。

代码&解析
  • 服务器端,请求地址为http://www.test.me/1.php,文件名为1.php
<?php
// 1.php
echo json_encode(['status' => 1, 'msg' => '成功'], JSON_UNESCAPED_UNICODE);
  • 客户端,入口地址为http://www.test1.me/1.html,文件名为1.html
// 注:此处的jq需自行下载放在当前代码所在目录
// 1.html
<script src="jquery-3.5.1.min.js"></script>
<script>
    $.ajax({
        url:'http://www.test.me/1.php',// 服务端地址
        success:function(res){
            console.log('res', res)
        },
        error:function(err_res) {
            console.log('err_res', err_res)
        }
    })
</script>

分析:假设客户端代码入口地址A为http://www.test1.me/1.html,服务端地址B为http://www.test.me/1.php,1.html中直接请求1.php,打开浏览器console面板,会出现跨域请求报错,详情如下

在这里插入图片描述
为了解决跨域的问题,最简单直接的方法是在服务器段添加一个头部,代码如下

<?php
// 1.php
header('Access-Control-Allow-Origin:*');
echo json_encode(['status' => 1, 'msg' => '成功'], JSON_UNESCAPED_UNICODE);

此处设置的头部,意思是允许所有源的请求访问;再次打开http://www.test1.me/1.html,跨域报错就没了。

只不过以上的处理方式,虽然使得跨域获取数据不成问题,但是跨域的时候还没带上身份凭证,需要再添加一些东西,同样,先看代码

// 1.html
<script src="jquery-3.5.1.min.js"></script>
<script>
    $.ajax({
        url:'http://www.test.me/1.php',

        crossDomain:true,
        xhrFields:{
            withCredentials: true
        },

        success:function(res){
            console.log('res', res)
        },
        error:function(err_res) {
            console.log('err_res', err_res)
        }
    })
</script>

对比一开始,多了crossDomain以及xhrFields两项,前者意思是进行跨域请求,后者的意思是简单的说,是否携带上身份信息。当然仅仅修改浏览器是不起作用的,还得对服务器端进行修改,代码如下。

<?php
// 1.php
header('Access-Control-Allow-Credentials:true');
header('Access-Control-Allow-Origin:'.getallheaders()['Origin']);

setcookie('aa', 'ad');

echo json_encode(['status' => 1, 'msg' => '成功'], JSON_UNESCAPED_UNICODE);

此处代码新增了Access-Control-Allow-Credentials一项,意为允许客户端携带身份凭证,值得注意的是,当使用Access-Control-Allow-Credentials时,Access-Control-Allow-Origin不能为*,可如以上代码设置为请求源。下面测试cookie信息是否已携带过来,新增2.php文件

<?php
// 2.php
header('Access-Control-Allow-Credentials:true');
header('Access-Control-Allow-Origin:'.getallheaders()['Origin']);

echo json_encode(['status' => 1, 'msg' => '成功', 'cookie' => $_COOKIE]);

先请求1.php,然后再请求2.php,从返回结果可以得知,cookie已成功设置且异步跨域请求已携带上cookie

完整代码如下:

<?php
// 1.php
header('Access-Control-Allow-Credentials:true');
header('Access-Control-Allow-Origin:'.getallheaders()['Origin']);

setcookie('aa', 'ad');

echo json_encode(['status' => 1, 'msg' => '成功'], JSON_UNESCAPED_UNICODE);
<?php
// 2.php
header('Access-Control-Allow-Credentials:true');
header('Access-Control-Allow-Origin:'.getallheaders()['Origin']);

echo json_encode(['status' => 1, 'msg' => '成功', 'cookie' => $_COOKIE]);
// 1.html
<button id="r2">request 2.php</button>
<script src="jquery-3.5.1.min.js"></script>
<script>
    $.ajax({
        url:'http://www.test.me/1.php',

        crossDomain:true,
        xhrFields:{
            withCredentials: true
        },

        success:function(res){
            console.log('res', res);
        },
        error:function(err_res) {
            console.log('err_res', err_res)
        }
    })

    $('#r2').click(function(){
        $.ajax({
            url:'http://www.test.me/2.php',

            crossDomain:true,
            xhrFields:{
                withCredentials: true
            },

            success:function(res){
                console.log('res', res);
            },
            error:function(err_res) {
                console.log('err_res', err_res)
            }
        })
    })
</script>

异常说明

如返回头部中的Set-Cookie项出现感叹号,是因为谷歌新版本升级后导致,解决办法为先后打开以下地址
chrome://flags/#same-site-by-default-cookies
chrome://flags/#cookies-without-same-site-must-be-secure
设置为Disabled,然后重启浏览器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值