JWT 的使用

  • Last updated on 2020-05-27
  • 642
PHP  
1、composer 引入 jwt 组件
  1. composer require firebase/php-jwt

 

2、编写代码(根据实际需要修改)
  1. <?php
  2. declare(strict_types = 1);
  3. namespace app\controllers;
  4. use app\common\Helper;
  5. use Firebase\JWT\JWT;
  6. use yii\base\Controller;
  7. class TestController extends Controller
  8. {
  9. /**
  10. * 登录
  11. *
  12. * @throws \Exception
  13. */
  14. public function actionLogin()
  15. {
  16. // 验证验证码、用户名及密码
  17. if (false) {
  18. return Helper::msg(0, '登录失败,验证码、用户名或密码错误');
  19. } else {
  20. // 如果验证通过,假设从数据库中获取到的用户信息
  21. $userInfo = [
  22. 'user_id' => 10000,
  23. 'user_name' => 'haveyb',
  24. 'is_admin' => 1,
  25. 'menus' => [1, 2, 6, 13],
  26. ];
  27. // 生成jwt,以供后续请求时,后端服务器身份校验
  28. $token = $this->getJwt($userInfo);
  29. // 返回给前端的数据,以供前端本次请求的数据显示
  30. $data = [
  31. 'user_id' => $userInfo['user_id'],
  32. 'user_name' => 'haveyb',
  33. 'menus' => $userInfo['menus'],
  34. 'token' => $token
  35. ];
  36. return Helper::msg(1, 'success', $data);
  37. }
  38. }
  39. /**
  40. * 验证用户是否登录,如果登录,返回用户id等信息,否则返回false
  41. */
  42. public function actionCheck()
  43. {
  44. // 假设客户端请求的token(正常流程应该是放在前端请求过来的header头中或者cookie中)
  45. $requestToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczpcL1wvd3d3LmhhdmV5Yi5jb20iLCJjcmVhdGVfdGltZSI6MTU4NjMzMzAwMSwidXNlcl9pZCI6MTAwMDAsImlzX2FkbWluIjoxfQ.VrGWf6nfhy8g5f-MufZK7J_OnOkUKiVHp4p9E9JavQw';
  46. // jwt 加解密密钥
  47. $secret = $this->getJwtSecret();
  48. // jwt 加解密方式
  49. $alg = $this->getJwtAlg();
  50. // 验证token是否有效
  51. try {
  52. $check = (array)JWT::decode($requestToken, $secret, [$alg]);
  53. } catch (\Exception $e) {
  54. return Helper::msg(0, '用户登录信息错误');
  55. }
  56. // 验证 jwt 有效期(可以有,可以没有,建议添加上)
  57. if (time() - $check['create_time'] > 86400) {
  58. return Helper::msg(0, '用户登录信息错误');
  59. }
  60. // 到数据库中查询用户id等信息,返回给调用的方法
  61. return Helper::msg(1, 'success', $check);
  62. }
  63. /**
  64. * 获取json web token
  65. *
  66. * @param $userInfo
  67. * @return string
  68. */
  69. private function getJwt($userInfo)
  70. {
  71. $secret = $this->getJwtSecret();
  72. $alg = $this->getJwtAlg();
  73. $currentTime = time();
  74. $returnData = [
  75. 'iss' => 'https://www.haveyb.com',
  76. 'create_time' => $currentTime,
  77. 'user_id' => $userInfo['user_id'],
  78. 'is_admin' => $userInfo['is_admin'],
  79. ];
  80. return JWT::encode($returnData, $secret, $alg);
  81. }
  82. /**
  83. * 返回jwt密钥
  84. *
  85. * @return string
  86. */
  87. private function getJwtSecret()
  88. {
  89. return 'BQXSD0PxCFPN/3xa06/94PWm++0ZKOHw83kP0=';
  90. }
  91. /**
  92. * 返回jwt加解密方式
  93. *
  94. * @return string
  95. */
  96. private function getJwtAlg()
  97. {
  98. return 'HS256';
  99. }
  100. }

 

3、校验结果:

访问 login 方法

访问check方法

说明:check 方法实际使用中应该由具体的方法调用,为的是校验身份以及获取用户id等信息。

 

4、安全上的防范

由于 jwt 一旦被其他人获取了,就可以伪造用户的身份进行操作,因此再安全上一定要注意。

(1)使用 https 协议

在http超文本传输协议加入SSL层,它在网络间通信是加密的,所以需要加密证书

(2)保证服务端用于生成token的签名不泄露,并比较晦涩难懂

(3)加入token 过期时间的校验

这样,即使其他人拿到token,没过多少时间,就过期了

(4)加入 token ip的校验,一旦用户ip发生变化,则要求用户重新登录

和加入过期时间类似,只要在生成token时,加入user_ip字段,后面客户端请求时,再校验下 user_ip  

 



Top