【问题标题】:I can't verify user with jwt我无法使用 jwt 验证用户
【发布时间】:2020-04-11 15:32:37
【问题描述】:

我正在尝试使用 Jwt 进行身份验证。 找了很多关于Jwt的例子,但是有一个地方我不明白。 我可以使用库轻松生成令牌,但无法验证 这是我使用的库

composer require firebase/php-jwt

我正在创建一个令牌

   // Allow from any origin
if (isset($_SERVER['HTTP_ORIGIN'])) {
    header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 86400');    // cache for 1 day
}

// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
        header("Access-Control-Allow-Methods: GET, POST, OPTIONS");         

    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
        header("Access-Control-Allow-Headers:        {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

    exit(0);
}


require_once('vendor/autoload.php');
use \Firebase\JWT\JWT; 
define('SECRET_KEY','Super-Secret-Key'); 
define('ALGORITHM','HS256');  


$postdata = file_get_contents("php://input");
$request = json_decode($postdata);

$action = $_GET['action'];

登录.php

   if ($action == 'login') {

 $email = 'freaky@jolly.com';
 $password = '12345678';


if($email == "freaky@jolly.com" && $password == "12345678"){

     $iat = time(); // time of token issued at
     $nbf = $iat + 10; //not before in seconds
     $exp = $iat + 60; // expire time of token in seconds

     $token = array(
         "iss" => "http://example.org",
         "aud" => "http://example.com",
         "iat" => $iat,
         "nbf" => $nbf,
         "exp" => $exp,
             "data" => array(
             "id" => 11,
             "email" => $email
         )
     );

    http_response_code(200);

    $jwt = JWT::encode($token, SECRET_KEY);


     $data_insert=array(
         'access_token' => $jwt, 
         'id'   => '007',
         'name' => 'Jolly',
         'time' => time(),
         'username' => 'FreakyJolly', 
         'email' => 'contact@freakyjolly.com', 
         'status' => "success",
         'message' => "Successfully Logged In"
     );


 }else{
     $data_insert=array(
     "data" => "0",
     "status" => "invalid",
     "message" => "Invalid Request"
     ); 
 } 

} else if($action == 'stuff'){

    if (! isset($_SERVER['argv'][1])) {
        exit('Please provide a key to verify');
    }
    $jwt = $_SERVER['argv'][1];

    try {
        $decoded = JWT::decode($jwt, SECRET_KEY, array(ALGORITHM));
        print_r($decoded);

    }catch (Exception $e){

     http_response_code(401);
     $data_insert=array(
     //"data" => $data_from_server,
     "jwt" => $jwt,
     "status" => "error",
     "message" => $e->getMessage()
     );

   } 
}

echo json_encode($data_insert);

创建令牌:http://www.ismailcakir.com/jwt/test2.php?action=login

{"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLm9yZyIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUuY29tIiwiaWF0IjoxNTg2NDM4NTg4LCJuYmYiOjE1ODY0Mzg1OTgsImV4cCI6MTU4NjQzODY0OCwiZGF0YSI6eyJpZCI6MTEsImVtYWlsIjoiZnJlYWt5QGpvbGx5LmNvbSJ9fQ.NylRpDkb4cLMxMGAg9ovmLerNf0dLPBHegqmPRDRxlE","id":"007","name":"Jolly","time":1586438588,"username":"FreakyJolly","email":"contact@freakyjolly.com","status":"success","message":"Successfully Logged In"}

资料:http://www.ismailcakir.com/jwt/test2.php?action=stuff

在这里,我收到 argv 变量未定义的警告,我无法调用您创建的令牌。 创建令牌后,我需要能够在不使用 cookie 或会话的情况下调用它。 我尝试了很多方法,但我无法理解如何服用。

【问题讨论】:

    标签: php jwt


    【解决方案1】:

    根据documentation

    注意:当 register_argc_argv 被禁用时,此变量不可用。

    这很可能是您的情况。您可以在配置中启用它,或者使用我推荐的$_SERVER superglobal,因为它不受配置差异的影响并且始终有效(包括 CLI):

    $jwt = $_SERVER['argv'][1];
    

    $argc 也一样。

    【讨论】:

    • 当我这样做时,我看到返回的结果是 null , ["argv"]=> array(0) { } ["argc"]=> int(0)
    • 另外,我可以看到 register_argc_argv 设置在服务器上打开。
    【解决方案2】:

    使用以下指令检查你得到的参数:

    <?php
    var_dump($argv);
    ?>
    

    从官方文档中可以看到:$_SERVER['argv']

    还请注意,$argv$argc 需要声明为全局,同时尝试在类方法中访问。

    【讨论】:

    • NULL,当我这样做时,我看到返回的结果是 null , ["argv"]=> array(0) { } ["argc"]=> int(0)
    • 这些方法我已经试过很多次了,但是都拿不到token。
    • 您是否以正确的方式使用脚本?如果从 cli 调用,通常第一个 arg 应该是脚本名称。
    • 我认为我正确使用了这些方法。无论如何,没有什么非常详细的,创建和调用令牌。但是我不能在这里取令牌,并且 arg 变量总是未定义或为 null 这是我的主要问题。您认为可能是什么问题?
    • 您能否举例说明如何从 CLI 调用脚本?
    【解决方案3】:

    为了能够获得令牌:

    $ _SERVER ['argv'] [1]

    然后,您需要从命令行 (CLI) 运行脚本,即:php &lt;script_name&gt; argc1 arg2 ...,然后您将能够从那里获取参数值,如果您使用浏览器或 API 调用,则需要使用 HTTP 方法 (GET/POST),

    或使用 JSON 接收调用:

    file_get_contents("php://input");

    看来你把所有东西都放在了你的代码中,你的代码需要重新编写。

    如果您在文件脚本中生成令牌,并且需要将其发送回不同的页面,则需要使用 GET/POST 请求,如果用户提供了值并且您需要保存或使用它,您需要通过方法接收它,下面是一个关于您的代码如何正常工作的示例(可以提供多种方式):

     if ($action == 'login') {
    
     $email = 'freaky@jolly.com';
     $password = '12345678';
    
    
    if($email == "freaky@jolly.com" && $password == "12345678"){
    
         $iat = time(); // time of token issued at
         $nbf = $iat + 10; //not before in seconds
         $exp = $iat + 60; // expire time of token in seconds
    
         $token = array(
             "iss" => "http://example.org",
             "aud" => "http://example.com",
             "iat" => $iat,
             "nbf" => $nbf,
             "exp" => $exp,
                 "data" => array(
                 "id" => 11,
                 "email" => $email
             )
         );
    
        http_response_code(200);
    
        $jwt = JWT::encode($token, SECRET_KEY);
    
        $_SESSION['token'] = $jwt;
        // $_COOKIE['token'] = $jwt ;
        // GET and POST can be used via a web form or CURL
    
         $data_insert=array(
             'access_token' => $jwt, 
             'id'   => '007',
             'name' => 'Jolly',
             'time' => time(),
             'username' => 'FreakyJolly', 
             'email' => 'contact@freakyjolly.com', 
             'status' => "success",
             'message' => "Successfully Logged In"
         );
    
    
     }else{
         $data_insert=array(
         "data" => "0",
         "status" => "invalid",
         "message" => "Invalid Request"
         ); 
     } 
    
    } else if($action == 'stuff'){
    
       /*
        * How to receive the generated token
        */
        if (!isset($_SESSION['token']))
        // or (!isset($_POST['token']));
        // or (!isset($_GET['token'])); 
        // or (!isset($_COOKIE['token']));
        {
            exit('Please provide a key to verify');
        }
    
        $jwt = $_SESSION['token']; 
    
        // or $jwt = $_GET['token']; 
        // or $jwt = $_POST['token']; 
        // or $jwt = $_COOKIE['token'];
    
        try {
            $decoded = JWT::decode($jwt, SECRET_KEY, array(ALGORITHM));
            print_r($decoded);
    
        }catch (Exception $e){
    
         http_response_code(401);
         $data_insert=array(
         //"data" => $data_from_server,
         "jwt" => $jwt,
         "status" => "error",
         "message" => $e->getMessage()
         );
    
       } 
    }
    
    echo json_encode($data_insert);
    

    你可以看看:

    PHP 中的 REST API 身份验证示例 - JWT 教程

    https://www.codeofaninja.com/2018/09/rest-api-authentication-example-php-jwt-tutorial.html

    【讨论】:

    • 使用cookies或季节有意义吗?这些值会在浏览器关闭时被删除。当我再次打开浏览器时,是否可以每次使用$_POST$_GET 获取令牌? 我的主要目标是我不希望用户每次都必须登录。
    • 我制作了一个基于浏览器的应用程序,用户正在登录它。但我不希望他们每次都登录。出于这个原因,我想在不使用季节或 cookie 的情况下使用 JWT 进行验证。
    • 浏览器关闭时不会删除 Cookie 和会话(仅会话存储)。会话在未过期或机器未重新启动或未以编程方式关闭时处于活动状态。
    • 如果需要使用 JWT 进行身份验证,则必须在每个请求中提供令牌(JWT 的典型用途是为其提供 Authorization Header 作为 Bearer TOKEN)。然后你必须制作一个 REST API 。你不能混合所有的请求和时尚,然后你期望一切都正常工作。
    • 我在最后编辑了上面的响应,并提供了一个有用的链接来实现将 JWT 用作 REST 服务。
    猜你喜欢
    • 2019-04-06
    • 2015-09-23
    • 2022-07-05
    • 2019-08-09
    • 1970-01-01
    • 2017-03-08
    • 2021-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多