标签:host pac date() ext available abi val 内容 UNC
这个扩展为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
将 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
, nbf
和 iat
声明默认在 ValidationData::__construct()
中使用当前 UNIX 时间 (time()
).ValidationData
的可选$leeway
参数将导致我们在验证基于时间的声明时使用该长度的秒数,iat
) 和“不在之前”(nbf
)索赔,假装我们在过去的更远exp
)索赔。这允许在发出服务器的时钟与时钟的时间不同的情况下我们可以使用签名来验证令牌在生成后是否未被修改。此扩展实现了Hmac、RSA和ECDSA签名(使用256、384和512)。
不允许发送到解析器的字符串指示要使用的签名算法,否则您的应用程序将易受严重的JWT安全漏洞的攻击。
下面的示例是安全的,因为Signer
中的选项是硬编码的,不受恶意用户的影响。
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签名基于公钥和私钥,因此您必须使用私钥生成并使用公钥验证:
$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应用程序
在本例中,我们将使用基本模板,但您也可以使用高级模板。
composer create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic yii2-jwt-test
安装组件
composer require sizeg/yii2-jwt
在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,
],
],
];
创建JwtValidationData类。在这里,您必须配置ValidationData来通知您要验证令牌的所有声明。
<?php
namespace 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();
}
}
修改方法 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;
}
新建控制器
<?php
namespace 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,
]);
}
}
发送简单的登录请求以获取令牌。这里我们不发送任何凭证来简化示例。正如我们在authenticator
行为操作login
中将authenticator
跳过该操作的身份验证检查指定为可选。
首先,我们尝试向rest/data发送请求,但不带令牌,并且获取错误 Unauthorized
然后我们重试请求,但已经用令牌添加了Authorization
标签:host pac date() ext available abi val 内容 UNC
原文地址:https://www.cnblogs.com/niuben/p/12175313.html