• 浏览器跨域请求之credentials


    -时间起源-

    前段时间,需要弄个简单的网站出来,访问远程的api服务。

    我是这么做的。首先是在搭建一个nodejs服务来运行前端页面。在我请求登录的时候,能成功返回相应的成功信息。然后,当我再次请求读取别的接口的时候,返回的信息确实提示我尚未登录。此时此刻,我一脸蒙逼。明明我已经登陆了啊。后来偶然得知这是因为浏览器的机制问题。

    -初步解决-

    大概的意思是,默认情况下,标准的跨域请求是不会发送cookie等用户认证凭据的。所以,当你再次访问远程api的时候,cookie是不会被带上的,于是乎,服务器理所当然地认为你还没有登录。MDN上的简单介绍 credentials 。用XMLHttpRequest请求的时候,我们需要设置属性 withCredentials=true ;

    1. var xhr = new XMLHttpRequest();  
    2. xhr.open('GET', 'http://www.xxx.com/api');  
    3. xhr.withCredentials = true;  
    4. xhr.onload = onLoadHandler;  
    5. xhr.send();  


    这样一来,cookie相关信息就会被带上了。

    需要注意的是,当这个属性为true的时候,远程服务器也要作相应的处理。在响应头那里设置  Access-Control-Allow-Credentials: true 。如果没有这个设置的话,浏览器就会报错。

    -引入新的问题-

    然后,还有一点需要说明的是,当服务器设置了Access-Control-Allow-Credentials: true之后,Access-Control-Allow-Origin就不能设置为 * 了(别问我为什么知道,我也说不清楚,可能是考虑到安全问题吧)。这么一来,那就陷入一个困境了:远程服务就是应该设置为允许浏览器跨域访问的啊,这个属性不能这么设置的话,应该怎么搞呢?于是我查啊查,搜啊搜,终于把这个问题完美解决了。

    -再度解决-

    Access-Control-Allow-Origin的作用在于,允许特定白名单用户(浏览器)访问我这个接口。当设置为 * 的时候,表示所有用户都能访问。如果值为 'http://xxx.com',则表示只接受来自这个域名的请求,其他的一律拒绝。而我们想要的效果就是想设置为 * 。自从用了Access-Control-Allow-Credentials: true,就不能设置Access-Control-Allow-Origin:'*'了。所有,我们可以换一种思路,当a用户进来的时候,我们设置a用户为白名单就好,同理b用户也是。也就是说,谁访问,我就设置谁为白名单。当浏览器进行跨域请求的时候,服务器能获取其相应的请求头,其中一个是 Origin 属性,表示请求的域。我们只要设置这域为白名单就好。每种服务器语言的设置方法可能都不一样,但原理是一样的。 大概如下

    1. responce.set('Access-Control-Allow-Origin', request.get('origin'));  

    好。ok了。

    --------------------------------------------------------------

    note: 上面的是使用原生的ajax请求,实际上很多人都选择诸如jquery这类框架。我之前是在beforeSend方法那里设置 xhr.withCredentials=true。然后悲剧地发现根本不能达到我的预期效果。其实,不是这么用的。应该是作为一个属性,而不是方法里面设置。与data属性并列设置就好。所以看起来是这样子的

    1. function func() {  
    2.         $.ajax({  
    3.             type: "GET",  
    4.             dataType: "json",  
    5.             xhrFields: {  
    6.                 withCredentials: true    // 要在这里设置  
    7.             },  
    8.             url: 'https://xxx.com/api/login',  
    9.             success: function (data) {  
    10.   
    11.             },  
    12.             beforeSend: function (xhr) {  
    13. //                下面的设置无效  
    14. //                xhr.withCredentials = true;  
    15.             },  
    16.             error: function (err) {  
    17.                 alert(JSON.stringify(err))  
    18.             }  
    19.         })  
    20.     }  


    好了,故事完了。

  • 相关阅读:
    MongoDB笔记
    mysql笔记
    08-下载中间件
    ubuntu1804安装pycharm2018.3.x
    02-CSS基础
    14-eval 函数
    13-文件
    12-模块和包
    11-异常
    有关dir和 unittest
  • 原文地址:https://www.cnblogs.com/cangqinglang/p/8823844.html
Copyright © 2020-2023  润新知