bao0558 / yii2-myguzzle
基于 Guzzlehttp 的 Guzzle
Requires
- php: >=5.6.0
- guzzlehttp/guzzle: >=6.0.0
- yiisoft/yii2: ~2.0.0
README
此扩展为 GUZZLE 提供了与 Yii 框架 2.0 的集成(需要 PHP 5.6+)。它包括基本的 HTTP 请求支持。
目录
安装
该软件包可在 Packagist 上找到,您可以使用 Composer 安装它。
composer require sizeg/yii2-jwt
依赖关系
- PHP 5.6+
- OpenSSL 扩展
- 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 参数来处理时钟偏差(见下文)。如果令牌的声称时间无效,但与验证时间的差异小于 $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
参数将使我们能够在验证基于时间的声明时使用该数量的秒数宽容,假装我们在 "Issued At"(《iat》)和 "Not Before"(《nbf》)声明中进一步未来,在 "Expiration Time"(《exp》)声明中假装我们进一步过去。这允许存在发行服务器和验证服务器时钟不同的场景,如 RFC 7519 第 4.1 节中所述。
令牌签名
我们可以使用签名来验证令牌在其生成后是否已被修改。此扩展实现了 Hmac、RSA 和 ECDSA 签名(使用 256、384 和 512)。
重要
不允许将发送给解析器的字符串决定要使用哪种签名算法,否则您的应用程序将容易受到 关键的 JWT 安全漏洞 的攻击。
下面的示例是安全的,因为 Signer
的选择是硬编码的,无法被恶意用户影响。
Hmac
Hmac 签名非常简单易用
$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 基本模板示例
基本方案
- 客户端发送凭证。例如,登录名+密码
- 后端验证它们
- 如果凭证有效,客户端将收到令牌
- 客户端存储令牌以供未来请求使用
逐步使用示例
-
创建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() { /** @var Jwt $jwt */ $jwt = Yii::$app->jwt; $signer = $jwt->getSigner('HS256'); $key = $jwt->getKey(); $time = time(); // 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 */ // 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
会跳过对该操作的认证检查。