保护 PHP Web 服务 (SOAP)

Securing a PHP Web service (SOAP)

我有一个 PHP Web 服务,它实际上可以帮助 CMS 对数据库进行一些更新。我一直在尝试在 Internet 上搜索解决方案,但还没有得到答案。

有什么方法可以检查向网络服务发出请求的用户是否有权这样做,即检查用户会话?

这是我的虚拟服务 (services.php)

<?php
    function GetMyUserName($i)
    {
        return "admin101";
    }
     $server = new SoapServer(null,array('uri' => ROOT."includes/services.php"));
     $server->addFunction('GetMyUserName');
     $server->handle();
?>

这是使用服务的 JavaScript (jQuery) [使用 SOAP 信封]

function GetMyUName() {
    var req1 = "";
    req1 += '<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">\n';
    req1 += '<soap:Body xmlns:m="includes/services.php">\n';
    req1 += "<m:GetMyUserName>\n";
    req1 += "</m:GetMyUserName>\n";
    req1 += "</soap:Body>\n";
    req1 += "</soap:Envelope>";

    $.ajax({
        url: "includes/services.php",
        type: "POST",
        data: req1,
        cache: false
    }).done(function (data) {
        $("#UsernameTb").html($(data).find("return").text());
    });
}

是否有类似我们在 ASP 的 WCF 中允许 Web 服务中的会话的东西。

如果此信息有点帮助,我正在使用 UserCake 进行身份验证。

概览

坦率地说,UserCake 看起来像是将近十年前写的。只需查看 UserCake 中的 login.php,它调用 die() 使用 header("Location: account.php") 重定向客户端和 echos HTML.

None 这些东西适合服务范例。最重要的是,UserCake 对重定向的依赖将使它几乎不可能在不进行实质性修改的情况下利用 SOAP 或 REST 接口。看看 securePage 函数...

//Check if a user has access to a page
function securePage($uri){
    // earlier code omitted for readability here...

    elseif(!isUserLoggedIn()) 
    {
        header("Location: login.php");
        return false;
    }

    // ...
}

服务通常不会重定向。他们 return 格式化响应有效载荷(例如 JSON 或 XML)并且可能使用 HTTP 代码来指示服务查询的结果是什么。也有像 OAuth 这样的例外,但这与手头的问题完全无关。

我建议选择一个合适的框架,Code Igniter if you want something simple, Symfony 如果你想要一些健壮的东西。两者都完全能够支持纯 HTML 页面、API 请求和身份验证/授权。但如果一定是UserCake...

击败 UserCake 提交

快速搜索告诉我们 Javascript must follow the redirect. The client would need to determine if the response is HTML or JSON, then handle accordingly. Code lifted from this answer and this one 说明了如何用 jQuery 完成此操作。

$.ajax({
  type: "POST",
  url: "services.php", 
  data: {action: 'someSecuredAction', data: 'some data for the command'}, 
  success: function(response, status, xhr){ 
    var ct = xhr.getResponseHeader("content-type") || "";
    if (ct.indexOf('html') > -1) {
     // If data looks like HTML, this is some page from UserCake
     // likely served by a redirect, just display it
     var newDoc = document.open("text/html", "replace");
     newDoc.write(response);
     newDoc.close();
    }
    if (ct.indexOf('json') > -1) {
     // If data looks like JSON we have a
     // successful 'service' response from the server
    } 
  }
});

理论上,浏览器会随请求传递任何相关的 cookie,因此会话应该在服务器上可用。请随时纠正我这一点,但从周围阅读听起来会话 cookie 将通过 AJAX 请求传递。

然后你的示例 'service' (services.php) 文件可能变成这样的东西(switch 只是一些人为的东西,让你知道如何从请求)

// If this ends up redirecting,
// the client should just pass it on through
securePage($_SERVER['PHP_SELF']);

switch($_POST['action']) {
   case 'someSecuredAction':
       // Again, if this redirects the client should be able to cope...
       $loggedInUser->checkPermission(['someSecuredAction']);

       // Do secured stuff here
       $aResponse = someSecureAction($_POST['data']);

   break;
}

// Now be nice enough to return the response as JSON
// like we might expect from an actual service
header('Content-Type: application/json;');
echo json_encode($aResponse);