HTTP身份验证和REST

时间:2013-01-29 21:34:30

标签: php jquery http-authentication

我正在构建一个允许移动应用与之通话的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

1 个答案:

答案 0 :(得分:2)

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

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

因此在PhoneGap中,没有浏览器强制实施同源规则 - 只有PhoneGap的配置(您可以控制)。 PhoneGap allows you to specify which domains (or all) your app will have access to。一旦列入白名单,您的代码就能够无限制地向这些域发出XHR请求。

唯一棘手的问题是,当使用jQuery发出XHR请求时,它会尝试将您的请求转换为JSONP,错误地认为它必须解决同源规则。

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

$.ajaxSetup({crossDomain:false});

关于Authorization, that's fairly simple。客户端发送字符串文字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标头作为响应("preflight request")。只有这样,浏览器才会发送实际的POST数据。