参考:https://blog.csdn.net/weixin_43303732/article/details/90443408
composer require tymon/jwt-auth
.env 文件下生成一个加密密钥
php artisan jwt:secret
修改文件:bootstrap\app.php
$app->register(Tymon\JWTAuth\Providers\LumenServiceProvider::class); // 添加代码(启用jwt)
<?php
namespace App\Models;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Model implements AuthenticatableContract, AuthorizableContract, JWTSubject
{
use Authenticatable, Authorizable, HasFactory;
....略
// 获取用户标识(即:用户的id,对应于生成的token的payload中的sub字段)
public function getJWTIdentifier()
{
return $this->getKey();
}
// payload中附加的自定义数据
public function getJWTCustomClaims()
{
return [
'data'=>$this->data
];
}
}
新建文件:app\Http\Controllers\AuthController.php
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
class AuthController
{
// 为登录正确的用户生成token
public function postLogin(Request $request)
{
$username = $request->json('username');
$password = $request->json('password');
// 数据库可以自已建一个表名叫users的表,要有name和password字段.
$user = User::where('name', $username)->where('password', $password)->first();
// payload中添加自定义数据
$user->data = [
'nickname'=>'测试',
'username'=>$username,
'url'=>'url'
];
if ($user) {
$token = Auth::login($user); // 生成token
return [
'status'=>200,
'data'=>[
'token'=>$token
]
];
}else{
return [
'status'=>500,
'message'=>'帐号不存在'
];
}
}
}
添加路由:routes\web.php
$router->post('/api/auth/login', '\App\Http\Controllers\AuthController@postLogin');
测试:
POST http://xxxx/api/auth/login
Content-Type:application/json
{
"username":"test",
"password":"123456"
}
返回:(https://tool.box3.cn/jwt.html 可以查看token解析出的结果,payload中的[sub]即数据库用户的id)
{
"status": 200,
"data":{
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC92Y2hhdGJvdC5sb2NcL2FwaVwvYXV0aFwvbG9naW4iLCJpYXQiOjE2MzEwODYyMTcsImV4cCI6MTYzMTA4OTgxNywibmJmIjoxNjMxMDg2MjE3LCJqdGkiOiJ4RXdEeThGcE5KM09NdUdoIiwic3ViIjoxLCJwcnYiOiIyM2JkNWM4OTQ5ZjYwMGFkYjM5ZTcwMWM0MDA4NzJkYjdhNTk3NmY3IiwiZGF0YSI6eyJuaWNrbmFtZSI6Ilx1NmQ0Ylx1OGJkNSIsInVzZXJuYW1lIjoidGVzdCIsInVybCI6InVybCJ9fQ.GmFd5AgT2FOzkW3O_c10dUPdRLj7FDLiu_HHZxqR0f4"
}
}
检查文件是否存在:config\auth.php
如果不存在可以把:vendor\laravel\lumen-framework\config\auth.php复制过来。
修改文件:config\auth.php
'guards' => [
'api' => [
'driver' => 'jwt', // 使用jwt
'provider' => 'users' // 使用providers中的users节的配置
],
],
'providers' => [
'users' => [
'driver' => 'eloquent', // 使用数据库模型(鉴权方法依赖数据库)
'model' => \App\Models\User::class, // 具体的模型(生成token时的用户来源)
],
],
修改文件:bootstrap\app.php
$app->configure('auth'); // 添加代码
$app->routeMiddleware([
'auth' => App\Http\Middleware\Authenticate::class, // 打开注释
]);
$app->register(App\Providers\AuthServiceProvider::class); // 打开注释
控制器中添加方法:app\Http\Controllers\AuthController.php
public function test(Request $request)
{
var_dump(Auth::user()->id);
}
配置路由:
$router->group([
'prefix'=>'api/jwt',
'middleware'=>'auth' // 使用在bootstrap\app.ph中打开的中间件鉴权
], function() use ($router){
$router->get('test', '\App\Http\Controllers\AuthController@test');
});
测试:
GET http://xxxx/api/jwt/test
Authorization:Bearer 这里填token(Bearer+空格+token)
返回:
int(1)
如token无效返回:
Unauthorized.
注:
jwt的配置参数可以查看:vendor\tymon\jwt-auth\config\config.php
可以使用vendor\tymon\jwt-auth\src\Http\Middleware\Authenticate.php代替默认的鉴权中间件。
php
参考:http://www.koukousky.com/back/2483.html
composer require lcobucci/jwt “^3.4”
<?php /** * jwt封装的一个简单的类 */ use Lcobucci\JWT\Configuration; use Lcobucci\JWT\Signer\Hmac\Sha256; use Lcobucci\JWT\Signer\Key\InMemory; use DateTimeImmutable; use Lcobucci\JWT\Token\Plain; use Lcobucci\JWT\Validation\RequiredConstraintsViolated; use Lcobucci\JWT\Validation\Constraint\SignedWith; class Service { /** * 配置秘钥加密 * @return Configuration */ public static function getConfig() { $configuration = Configuration::forSymmetricSigner( // You may use any HMAC variations (256, 384, and 512) new Sha256(), // replace the value below with a key of your own! InMemory::base64Encoded('YWFhc0pOU0RLSkJITktKU0RiamhrMTJiM2Joa2ox') // You may also override the JOSE encoder/decoder if needed by providing extra arguments here ); return $configuration; } /** * 签发令牌 */ public static function createToken() { $config = self::getConfig(); assert($config instanceof Configuration); $now = new DateTimeImmutable(); // 时间必须用这个类,否则报错 $token = $config->builder() // 签发人 ->issuedBy('http://example.com') // 受众 ->permittedFor('http://example.org') // JWT ID 编号 唯一标识 ->identifiedBy('123') // 签发时间 ->issuedAt($now) // 在1分钟后才可使用 ->canOnlyBeUsedAfter($now->modify('+1 minute')) // 过期时间1小时 ->expiresAt($now->modify('+1 hour')) // 自定义uid 额外参数 ->withClaim('uid', 1) // 自定义header 参数 ->withHeader('foo', 'bar') // 生成token ->getToken($config->signer(), $config->signingKey()); //result: //eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImZvbyI6ImJhciJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLmNvbSIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUub3JnIiwianRpIjoiNGYxZzIzYTEyYWEiLCJpYXQiOjE2MDk0Mjk3MjMsIm5iZiI6MTYwOTQyOTc4MywiZXhwIjoxNjA5NDMzMzIzLCJ1aWQiOjF9.o4uLWzZjk-GJgrxgirypHhXKkMMUEeL7z7rmvmW9Mnw //base64 decode: //{"typ":"JWT","alg":"HS256","foo":"bar"}{"iss":"http:\/\/example.com","aud":"http:\/\/example.org","jti":"4f1g23a12aa","iat":1609429723,"nbf":1609429783,"exp":1609433323,"uid":1}[6cb`"*Gr0ńxoL return $token->toString(); } /** * 解析令牌 */ public static function parseToken(string $token) { $config = self::getConfig(); assert($config instanceof Configuration); $token = $config->parser()->parse('eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImZvbyI6ImJhciJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLmNvbSIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUub3JnIiwianRpIjoiNGYxZzIzYTEyYWEiLCJpYXQiOjE2MDk0Mjk3MjMsIm5iZiI6MTYwOTQyOTc4MywiZXhwIjoxNjA5NDMzMzIzLCJ1aWQiOjF9.o4uLWzZjk-GJgrxgirypHhXKkMMUEeL7z7rmvmW9Mnw' ); assert($token instanceof Plain); dump($token->headers()); // Retrieves the token headers dump($token->claims()); // Retrieves the token claims } /** * 验证令牌 */ public static function validationToken(string $token) { $config = self::getConfig(); assert($config instanceof Configuration); $token = $config->parser()->parse($token); assert($token instanceof Plain); //Lcobucci\JWT\Validation\Constraint\IdentifiedBy: 验证jwt id是否匹配 //Lcobucci\JWT\Validation\Constraint\IssuedBy: 验证签发人参数是否匹配 //Lcobucci\JWT\Validation\Constraint\PermittedFor: 验证受众人参数是否匹配 //Lcobucci\JWT\Validation\Constraint\RelatedTo: 验证自定义cliam参数是否匹配 //Lcobucci\JWT\Validation\Constraint\SignedWith: 验证令牌是否已使用预期的签名者和密钥签名 //Lcobucci\JWT\Validation\Constraint\ValidAt: 验证要求iat,nbf和exp(支持余地配置) //验证jwt id是否匹配 $validate_jwt_id = new \Lcobucci\JWT\Validation\Constraint\IdentifiedBy('123'); $config->setValidationConstraints($validate_jwt_id); //验证签发人url是否正确 $validate_issued = new \Lcobucci\JWT\Validation\Constraint\IssuedBy('http://example.com'); $config->setValidationConstraints($validate_issued); //验证客户端url是否匹配 $validate_aud = new \Lcobucci\JWT\Validation\Constraint\PermittedFor('http://example.org'); $config->setValidationConstraints($validate_aud); //验证是否过期 $timezone = new \DateTimeZone('Asia/Shanghai'); $now = new \Lcobucci\Clock\SystemClock($timezone); $validate_jwt_at = new \Lcobucci\JWT\Validation\Constraint\ValidAt($now); $config->setValidationConstraints($validate_jwt_at); $constraints = $config->validationConstraints(); try { $config->validator()->assert($token, ...$constraints); } catch (RequiredConstraintsViolated $e) { // list of constraints violation exceptions: var_dump($e->violations()); } } } JAVA com.auth0 java-jwt 3.18.2 import com.auth0.jwt.JWT; import com.auth0.jwt.JWTVerifier; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.exceptions.JWTDecodeException; import com.auth0.jwt.interfaces.DecodedJWT; public String getAccount(){ // 不校验key,直接解析 DecodedJWT jwt = JWT.decode(account); // 校验key后解析 // String publicKey = ""; // Algorithm algorithm = Algorithm.HMAC256(publicKey); // publicKey需要与生成方的一致 // JWTVerifier verifier = JWT.require(algorithm).build(); // DecodedJWT jwt = verifier.verify(account); return jwt.getClaim("account").asString(); }