0

我正在构建一个允许移动应用程序与之对话的 PHP Api。该应用程序目前更像是一个技术演示,用于测试技术和想法。

为了保护应用程序请求,某些事情需要身份验证。

因此,让我们以以下为例:

$('form').submit(function(e){

    e.preventDefault();

    var form = $(this);

    var data = form.serialize();

    $.ajax({
        type: 'POST',
        url: form.attr('action'),
        data: data,
        success: function(response){

            // show success message or error depending on authentication

        },
        error: function(a,b,c) {

        }   
    });

});

我还header('Access-Control-Allow-Origin: *');用来允许应用程序与它和通配符对话,因为它目前只是一个测试。然而,在现实生活中,我不会有一个域,因为它将从移动设备而不是另一个域(很可能是PhoneGap)运行。

我在网上环顾四周并遇到了,HTTP Authorization但无论我阅读了多少文档,我都无法理解它。

它的一个例子是这样的:

Authorization: TRUEREST username=john&password=test&apikey=247b5a2f72df375279573f2746686daa

我已经考虑过根据我在 jQuery 文档中看到的内容来传递所说的数据:

data: {
    username: 'john',
    password: 'test',
    apiKey: '247b5a2f72df375279573f2746686daa'
},
headers: {
    Authorization: "TRUEREST"
},

在发回 JSON 之前,我可以先检查数据库中是否存在用户名和密码,也可能以同样的方式检查 Api 密钥。但我根本不了解 TRUEREST 部分或它可以为代码提供什么?

更新

我一直在我的 jQuery 代码中尝试以下内容:

headers: {
                            Authorization: "TRUEREST",
                            username: 'dave',
                            password: 'test',
                            apiKey: 'qwe123'    
                        },

然后在我的 PHP 中:

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Headers: Authorization,Content-type,username,password,apiKey');

if($_SERVER['REQUEST_METHOD'] == 'POST')
{


    $headers = $_SERVER['HTTP_AUTHORIZATION'];
    $parts = explode(' ', $_SERVER['HTTP_AUTHORIZATION']);

    header('Content-type: application/json');
    print json_encode($parts);

    exit;

返回的 JSON 只是 TRUEREST!PHP没有看到其他任何人。但是,如果我查看网络检查器,它们会被很好地发送。但注意到有两种类型的请求正在发出 POST 和 OPTIONS。

有任何想法吗?

我将这些更新基于我在这里阅读的内容:https ://github.com/kvz/cakephp-rest-plugin/blob/master/Controller/Component/RestComponent.php#L516

4

1 回答 1

2

首先,您无需担心 PhoneGap 应用程序中的跨域限制。

请记住,执行同源规则的是浏览器。您的服务器可能唯一的参与是当不同域上的页面尝试对您服务器上的某些内容发出 XHR 请求时;CORS规范概述了如何处理。如果您使用适当Access-Control-Allow-Origin的标头进行响应,则允许 XHR 请求不受限制。

所以在PhoneGap 中,没有浏览器强制执行同源规则——只有PhoneGap 的配置(由您控制​​)。PhoneGap允许您指定您的应用程序可以访问的域(或所有域)。列入白名单后,您的代码将能够不受限制地向这些域发出 XHR 请求。

唯一棘手的是,当使用 jQuery 发出 XHR 请求时,它会尝试将您的请求转换为 JSONP,错误地假设它必须围绕同源规则工作。

要解决此问题,您可以强制 jQuery 始终使用 XHR:

$.ajaxSetup({crossDomain:false});

关于Authorization,这相当简单。客户端发送字符串文字Basic、空格,然后是用户名、冒号和 base64 编码的密码。

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

解码 base64 数据产生Aladdin:open sesame.


根据您添加的 jQuery 代码段,您的 HTTP 请求如下所示:

POST /form.php HTTP/1.1
Host: example.com
X-Requested-With: XmlHttpRequest
Authorization: TRUEREST
username: dave
password: test
apiKey: qwe123
...

应该很明显为什么$_SERVER['HTTP_AUTHORIZATION']只包含TRUEREST:其他项目是完全独立的(和无效的)标题。尝试:

headers: {
    Authorization: 'X-My-API ' + $.param({
        username: 'dave',
        password: 'test',
        apiKey: 'qwe123'
    })
}

现在您的请求将如下所示:

POST /form.php HTTP/1.1
Host: example.com
X-Requested-With: XmlHttpRequest
Authorization: X-My-API username=dave&password=test&apiKey=qwe123
...
  • $.param将对象序列化为 URL 编码的查询字符串。
  • 您可能应该考虑对授权数据进行 base64 编码,就像 HTTP Basic auth 一样。这将确保 HTTP 标头中只有 [A-Za-z0-9+/=](可打印)字符,从而可能避免安全问题。
  • 我对 RFC 的要求并不完全清楚,但按照惯例,HTTP 的非标准扩展通常以X-为前缀。由于您的授权方案是非标准的,您应该这样做。
  • OPTIONS您看到的请求是 CORS 在工作。如果您在跨域 XHR 请求中指定自定义标头,浏览器首先检查服务器以查看它是否发送Access-Control-Allow-Origin标头作为响应(“预检请求”)。只有这样,浏览器才会发送实际POST的数据。
于 2013-01-29T22:18:54.263 回答