0


Yii2 JWT

Yii2 JWT

这个扩展为Yii framework 2.0提供了JWT集成(需要PHP 5.6+)。它包括基本的HTTP身份验证支持。

目录

安装

Package is available on Packagist,
you can install it using Composer.

composer require sizeg/yii2-jwt

依赖关系

  • PHP 5.6+
  • OpenSSL Extension
  • lcobucci/jwt 3.3

基本用法

jwt

组件添加到配置文件中,

'components' => [
    'jwt' => [
      'class' => \sizeg\jwt\Jwt::class,
      'key'   => 'secret',
    ],
],

按如下方式配置

authenticator

行为。

namespace app\controllers;

class ExampleController extends \yii\rest\Controller
{

    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        $behaviors = parent::behaviors();
        $behaviors['authenticator'] = [
            'class' => \sizeg\jwt\JwtHttpBearerAuth::class,
        ];

        return $behaviors;
    }
}

也可以将其与

CompositeAuth

参考文献 一起用于文档

创建

有些方法被标记为已弃用,并很快将从lcobucci/jwt 4.x回传内容以创建升级路径。

只需使用构建器创建一个新的JWT/JWS令牌:

$time = time();
$token = Yii::$app->jwt->getBuilder()
            ->issuedBy('http://example.com') // Configures the issuer (iss claim)
            ->permittedFor('http://example.org') // Configures the audience (aud claim)
            ->identifiedBy('4f1g23a12aa', true) // Configures the id (jti claim), replicating as a header item
            ->issuedAt($time) // Configures the time that the token was issue (iat claim)
            ->canOnlyBeUsedAfter($time + 60) // Configures the time that the token can be used (nbf claim)
            ->expiresAt($time + 3600) // Configures the expiration time of the token (exp claim)
            ->withClaim('uid', 1) // Configures a new claim, called "uid"
            ->getToken(); // Retrieves the generated token

$token->getHeaders(); // Retrieves the token headers
$token->getClaims(); // Retrieves the token claims

echo $token->getHeader('jti'); // will print "4f1g23a12aa"
echo $token->getClaim('iss'); // will print "http://example.com"
echo $token->getClaim('uid'); // will print "1"
echo $token; // The string representation of the object is a JWT string (pretty easy, right?)

从字符串分析

使用解析器从JWT字符串创建一个新的令牌(以前面的令牌为例):

$token = Yii::$app->jwt->getParser()->parse((string) $token); // Parses from a string
$token->getHeaders(); // Retrieves the token header
$token->getClaims(); // Retrieves the token claims

echo $token->getHeader('jti'); // will print "4f1g23a12aa"
echo $token->getClaim('iss'); // will print "http://example.com"
echo $token->getClaim('uid'); // will print "1"

验证

我们可以很容易地验证令牌是否有效(以前面的令牌为例):

$data = Yii::$app->jwt->getValidationData(); // It will use the current time to validate (iat, nbf and exp)
$data->setIssuer('http://example.com');
$data->setAudience('http://example.org');
$data->setId('4f1g23a12aa');

var_dump($token->validate($data)); // false, because we created a token that cannot be used before of `time() + 60`

$data->setCurrentTime(time() + 61); // changing the validation time to future

var_dump($token->validate($data)); // true, because validation information is equals to data contained on the token

$data->setCurrentTime(time() + 4000); // changing the validation time to future

var_dump($token->validate($data)); // false, because token is expired since current time is greater than exp

我们还可以使用$leeway参数来处理时钟偏差(见下面的注释)。

如果token的声明时间无效,但与验证时间之间的差异小于$leeway,

那么令牌仍然被认为是有效的

'components' => [
    'jwt' => [
        'class' => \sizeg\jwt\Jwt:class,
        'key'   => 'secret',
        'jwtValidationData' => [
            'class' => \sizeg\jwt\JwtValidationData::class,
             // configure leeway 
            'leeway' => 20,
        ],
    ],
],
$dataWithLeeway = Yii::$app->jwt->getValidationData();
$dataWithLeeway->setIssuer('http://example.com');
$dataWithLeeway->setAudience('http://example.org');
$dataWithLeeway->setId('4f1g23a12aa');

var_dump($token->validate($dataWithLeeway)); // false, because token can't be used before now() + 60, not within leeway

$dataWithLeeway->setCurrentTime($time + 61); // changing the validation time to future

var_dump($token->validate($dataWithLeeway)); // true, because current time plus leeway is between "nbf" and "exp" claims

$dataWithLeeway->setCurrentTime($time + 3610); // changing the validation time to future but within leeway

var_dump($token->validate($dataWithLeeway)); // true, because current time - 20 seconds leeway is less than exp

$dataWithLeeway->setCurrentTime($time + 4000); // changing the validation time to future outside of leeway

var_dump($token->validate($dataWithLeeway)); // false, because token is expired since current time is greater than exp

重要提示

  • 您必须配置' ValidationData ,通知所有要验证令牌的声明。
  • 如果 ValidationData 包含未在令牌中使用的声明,或者令牌具有未在ValidationData 中配置的声明,则 Token::validate()将忽略这些声明。
  • exp, nbfiat 声明默认在 ValidationData::__construct() 中使用当前 UNIX 时间 (time()).
  • ValidationData的可选$leeway 参数将导致我们在验证基于时间的声明时使用该长度的秒数, 假装我们在未来的“发出时间”(iat) 和“不在之前”(nbf)索赔,假装我们在过去的更远 对于“过期时间”(exp)索赔。这允许在发出服务器的时钟与时钟的时间不同的情况下 验证服务器,如RFC 7519第4.1节所述。

令牌签名

我们可以使用签名来验证令牌在生成后是否未被修改。此扩展实现了Hmac、RSA和ECDSA签名(使用256、384和512)。

重要提示

不允许发送到解析器的字符串指示要使用的签名算法,否则您的应用程序将易受严重的JWT安全漏洞的攻击。

下面的示例是安全的,因为

Signer

中的选项是硬编码的,不受恶意用户的影响。

Hmac

Hmac signatures are really simple to be used:

$jwt = Yii::$app->jwt;
$signer = $jwt->getSigner('HS256');
$key = $jwt->getKey();
$time = time();

$token = $jwt->getBuilder()
            ->issuedBy('http://example.com') // Configures the issuer (iss claim)
            ->permittedFor('http://example.org') // Configures the audience (aud claim)
            ->identifiedBy('4f1g23a12aa', true) // Configures the id (jti claim), replicating as a header item
            ->issuedAt($time) // Configures the time that the token was issue (iat claim)
            ->canOnlyBeUsedAfter($time + 60) // Configures the time that the token can be used (nbf claim)
            ->expiresAt($time + 3600) // Configures the expiration time of the token (exp claim)
            ->withClaim('uid', 1) // Configures a new claim, called "uid"
            ->getToken($signer, $key); // Retrieves the generated token

var_dump($token->verify($signer, 'testing 1')); // false, because the key is different
var_dump($token->verify($signer, 'testing')); // true, because the key is the same

RSA 和 ECDSA

RSA和ECDSA签名基于公钥和私钥,因此您必须使用私钥生成并使用公钥验证:

$jwt = Yii::$app->jwt;
$signer = $jwt->getSigner('RS256'); // you can use 'ES256' if you're using ECDSA keys
$privateKey = $jwt->getKey('file://{path to your private key}');
$time = time();

$token = $jwt->getBuilder()
            ->issuedBy('http://example.com') // Configures the issuer (iss claim)
            ->permittedFor('http://example.org') // Configures the audience (aud claim)
            ->identifiedBy('4f1g23a12aa', true) // Configures the id (jti claim), replicating as a header item
            ->issuedAt($time) // Configures the time that the token was issue (iat claim)
            ->canOnlyBeUsedAfter($time + 60) // Configures the time that the token can be used (nbf claim)
            ->expiresAt($time + 3600) // Configures the expiration time of the token (exp claim)
            ->withClaim('uid', 1) // Configures a new claim, called "uid"
            ->getToken($signer, $privateKey); // Retrieves the generated token
            
$publicKey = $jwt->getKey('file://{path to your public key}');

var_dump($token->verify($signer, $publicKey)); // true when the public key was generated by the private one =)

**很重要的一点是,如果您使用的是RSA密钥,则不应该调用ECDSA签名者(反之亦然),否则

sign()

verify()

将引发异常!**

Yii2基本模板示例

基本方案

  1. 客户端发送凭据。例如,登录+密码
  2. 后端验证它们
  3. 如果凭据是有效的客户端接收令牌
  4. 未来请求的客户端存储令牌

分步使用示例

  1. 创建Yii2应用程序在本例中,我们将使用基本模板,但您也可以使用高级模板。composer create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic yii2-jwt-test
  2. 安装组件composer require sizeg/yii2-jwt
  3. 在config/web.php中添加 components 部分$config = [ 'components' => [ // other default components here.. 'jwt' => [ 'class' => \sizeg\jwt\Jwt::class, 'key' => 'secret', // You have to configure ValidationData informing all claims you want to validate the token. 'jwtValidationData' => \app\components\JwtValidationData::class, ], ],];
  4. 创建JwtValidationData类。在这里,您必须配置ValidationData来通知您要验证令牌的所有声明。<?phpnamespace app\components;class JwtValidationData extends \sizeg\jwt\JwtValidationData{ /** * @inheritdoc */ public function init() { $this->validationData->setIssuer('http://example.com'); $this->validationData->setAudience('http://example.org'); $this->validationData->setId('4f1g23a12aa'); parent::init(); }}
  5. 修改方法 app\models\User::findIdentityByAccessToken()``````/** * {@inheritdoc} * @param \Lcobucci\JWT\Token $token */ public static function findIdentityByAccessToken($token, $type = null) { foreach (self::$users as $user) { if ($user['id'] === (string) $token->getClaim('uid')) { return new static($user); } } return null; }
  6. 新建控制器<?phpnamespace app\controllers;use sizeg\jwt\Jwt;use sizeg\jwt\JwtHttpBearerAuth;use Yii;use yii\rest\Controller;class RestController extends Controller{ /** * @inheritdoc */ public function behaviors() { $behaviors = parent::behaviors(); $behaviors['authenticator'] = [ 'class' => JwtHttpBearerAuth::class, 'optional' => [ 'login', ], ]; return $behaviors; } /** * @return \yii\web\Response */ public function actionLogin() { $request = Yii::$app->getRequest(); $jwt = Yii::$app->jwt; $time = time(); $token = $jwt->getBuilder() ->issuedBy($request->getHostInfo()) ->permittedFor(isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '') ->identifiedBy(Yii::$app->security->generateRandomString(10), true) //生成随机的盐值 ->issuedAt($time)// 设置生成token的时间 ->expiresAt($time + 3600)//设置token过期时间 ->withClaim('uid', 100)//配置一个名为uid的新声明 ->getToken($jwt->getSigner('HS256'), $jwt->getKey()); // Previous implementation /* $token = $jwt->getBuilder() ->setIssuer('http://example.com')// Configures the issuer (iss claim) ->setAudience('http://example.org')// Configures the audience (aud claim) ->setId('4f1g23a12aa', true)// Configures the id (jti claim), replicating as a header item ->setIssuedAt(time())// Configures the time that the token was issue (iat claim) ->setExpiration(time() + 3600)// Configures the expiration time of the token (exp claim) ->set('uid', 100)// Configures a new claim, called "uid" ->sign($signer, $jwt->key)// creates a signature using [[Jwt::$key]] ->getToken(); // Retrieves the generated token // 示例 $jwt = Yii::$app->jwt; $signer = $jwt->getSigner('HS256'); $key = $jwt->getKey(); $time = time(); // Adoption for lcobucci/jwt ^4.0 version $token = $jwt->getBuilder() ->issuedBy('http://example.com')// Configures the issuer (iss claim) ->permittedFor('http://example.org')// Configures the audience (aud claim) ->identifiedBy('4f1g23a12aa', true)// Configures the id (jti claim), replicating as a header item ->issuedAt($time)// Configures the time that the token was issue (iat claim) ->expiresAt($time + 3600)// Configures the expiration time of the token (exp claim) ->withClaim('uid', 100)// Configures a new claim, called "uid" ->getToken($signer, $key); // Retrieves the generated token */ return $this->asJson([ 'token' => (string)$token, ]); } /** * @return \yii\web\Response */ public function actionData() { return $this->asJson([ 'success' => true, ]); }}
  7. 发送简单的登录请求以获取令牌。这里我们不发送任何凭证来简化示例。正如我们在authenticator行为操作login中将authenticator跳过该操作的身份验证检查指定为可选。image
  8. 首先,我们尝试向rest/data发送请求,但不带令牌,并且获取错误 Unauthorizedimage
  9. 然后我们重试请求,但已经用令牌添加了Authorizationimage
标签: python java php

本文转载自: https://blog.csdn.net/Guzarish/article/details/118627128
版权归原作者 牛奔 所有, 如有侵权,请联系我们删除。

“Yii2 JWT”的评论:

还没有评论