如何安全地实现“基于令牌的身份验证”以访问在 PHPFox 中开发的网站资源(即功能和数据)?

Posted

技术标签:

【中文标题】如何安全地实现“基于令牌的身份验证”以访问在 PHPFox 中开发的网站资源(即功能和数据)?【英文标题】:How to implement 'Token Based Authentication' securely for accessing the website's resources(i.e. functions and data) that is developed in PHPFox? 【发布时间】:2015-05-21 04:21:19 【问题描述】:

我想使用 PHPFox 开发的网站代码中的方法和资源。

基本上,我会收到来自iPhone/android 的请求,我会从 phpFox 代码中获取请求并传递给相应的函数,从该函数中获取响应并将其返回给设备。

为此,我使用 Slim 框架 开发了 REST API。

但我目前面临的主要障碍是访问 PHPFox 网站的资源(即函数和数据)。

我不明白我应该如何使用 '基于令牌的身份验证' 对用户进行身份验证才能访问网站的资源。

如果有人可以通过一些有用的工作示例指导我正确的方向,那对我真的很有帮助。

注意:“基于令牌的身份验证”的提议实施应该非常安全且速度快。不应以任何方式损害安全性。

以下是我自己尝试的代码,但我不知道它是对还是错。我的方法是对还是错。请有人分析它并让我知道您对此的反馈。

要创建令牌,我使用此函数,该函数将用户数据作为参数

define('SECRET_KEY', "fakesecretkey");

function createToken($data)

    /* Create a part of token using secretKey and other stuff */
    $tokenGeneric = SECRET_KEY.$_SERVER["SERVER_NAME"]; // It can be 'stronger' of course

    /* Encoding token */
    $token = hash('sha256', $tokenGeneric.$data);

    return array('token' => $token, 'userData' => $data);

因此用户可以验证自己并接收包含令牌(genericPart + 他的数据,已编码)的数组,并且 hisData 未编码:

function auth($login, $password)

    // we check user. For instance, it's ok, and we get his ID and his role.
    $userID = 1;
    $userRole = "admin";

    // Concatenating data with TIME
    $data = time()."_".$userID."-".$userRole;
    $token = createToken($data);
    echo json_encode($token);

然后用户可以将他的令牌 + 他的未编码数据发送给我以便检查:

define('VALIDITY_TIME', 3600);

function checkToken($receivedToken, $receivedData)

    /* Recreate the generic part of token using secretKey and other stuff */
    $tokenGeneric = SECRET_KEY.$_SERVER["SERVER_NAME"];

    // We create a token which should match
    $token = hash('sha256', $tokenGeneric.$receivedData);   

    // We check if token is ok !
    if ($receivedToken != $token)
    
        echo 'wrong Token !';
        return false;
    

    list($tokenDate, $userData) = explode("_", $receivedData);
    // here we compare tokenDate with current time using VALIDITY_TIME to check if the token is expired
    // if token expired we return false

    // otherwise it's ok and we return a new token
    return createToken(time()."#".$userData);   


$check = checkToken($_GET['token'], $_GET['data']);
if ($check !== false)
    echo json_encode(array("secureData" => "Oo")); // And we add the new token for the next request

我说的对吗?

谢谢。

【问题讨论】:

【参考方案1】:

首先,您应该了解什么是基于令牌的身份验证。可以这样解释。

基于令牌的身份验证系统背后的一般概念是 简单的。允许用户输入他们的用户名和密码,以便 获取允许他们获取特定资源的令牌 - 不使用他们的用户名和密码。一旦他们的令牌被 获得后,用户可以提供令牌 - 它提供对 一段时间内的特定资源 - 到远程站点。

Read more

现在让我们看看在您的 REST Web 服务中实现它的步骤是什么。

它将使用以下控制流程:

用户在登录表单中提供用户名和密码,然后单击登录。 发出请求后,通过在数据库中查询来验证后端的用户。如果请求有效,则通过 使用从数据库中获取的用户信息,然后返回 该信息在响应标头中,以便我们可以存储令牌 本地存储中的浏览器。 在每个请求标头中提供令牌信息,以访问应用程序中的受限端点。 如果从请求头信息中获取的token有效,则让用户访问指定的端点,并以JSON或 XML。

控制流程见下图

您可能想知道什么是 JWT

JWT 代表 JSON Web Token,是一种用于 授权标头。此令牌可帮助您设计通信 以安全的方式在两个系统之间。让我们将 JWT 改写为“承载者” 令牌”用于本教程的目的。不记名令牌包括 三部分:header、payload、signature。

标头是令牌中保存令牌类型和加密方法的部分,以 base64 编码。 有效负载包括信息。您可以放置​​任何类型的数据,如用户信息、产品信息等,所有这些数据也都存储在 base64 编码。 签名由标头、有效负载和密钥的组合组成。密钥必须安全地保存在服务器端。 您可以在下面看到 JWT 架构和示例令牌;

您不需要实现不记名令牌生成器,因为您可以使用php-jwt。

希望以上内容能解释您的困惑。如果您在实施基于令牌的身份验证时遇到任何问题,请告诉我。我可以帮你。

【讨论】:

首先感谢您对我的问题表现出兴趣并让我了解真正的“基于令牌的身份验证”是什么。但是您能否从头开始向我提供 php-jwt 的工作示例,以便我可以将其复制到我的系统中。代码应该包括从创建数据库表、PHP 和 mysql 之间的连接、然后创建安全令牌、检查当前登录用户的安全令牌的有效性等所有内容。还有一件事可能是多个用户登录一次并且对于每个用户,这个“基于令牌的身份验证”应该可以工作。泰。 请看我问题正文的结尾。我试过一个代码。你能检查一下它是否正确。我做对了吗? 有需要改进的地方,但没关系。您需要做的是使用 php-jwt 生成和验证令牌。我会好很多。但这也没关系。 嘿,您能按照我在第一条评论中的要求提供完整的 php-jwt 实现代码并将其添加到您的答案中吗?这对我来说真的很棒。由于这是与网站资源安全相关的非常脆弱的问题,我不想因编码不当而冒任何风险。因此,我恳请您根据要求向我提供 php-jwt 的完整代码,这将是非常安全和高效的答案。再次感谢您的帮助。期待你的php-jwt实现代码!!! 此处提供了示例代码库github.com/firebase/php-jwt。请参考。如果您有任何问题,请告诉我。

以上是关于如何安全地实现“基于令牌的身份验证”以访问在 PHPFox 中开发的网站资源(即功能和数据)?的主要内容,如果未能解决你的问题,请参考以下文章

基于令牌的身份验证的安全性

在基于令牌的身份验证中使用刷新令牌是不是安全?

使用 Spring 和 JWT 进行基于令牌的身份验证

Web API 中基于令牌的身份验证,无需任何用户界面

带有烧瓶安全扩展的基于令牌的身份验证

用户和单独模块的基于令牌的身份验证