基于RuoYi-Vue3-master,后端thinkphp5开发Api——(5)用jwt生成token,并加密token
·
1.安装jwt
composer require firebase/php-jwt
2.创建服务类Jwt生成、验证token
(1)在extra文件夹下新建system.php配置文件
<?php
return [
// Jwt 参数配置
'token_name' => 'Authorization', // 令牌名称
'jwt_iss' => 'https://xxx.xxxxx.net', // 签发者
"jwt_aud" => 'https://xxx.xxxxx.net', // 接收该JWT的一方
'jwt_key' => 'xxxxxx', // 加密密钥
'jwt_algo' => 'HS256', // 算法
'jwt_exp_hour' => 24, // jwt过期时间
'pass_salt' => 'xxxxxxx',
];
(2)创建服务类JwtHandle.php
<?php
namespace app\lib\server;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
use think\Controller;
use think\Request;
class JwtHandle extends Controller
{
protected $key;
protected $jwtAlgo;
protected $jwtIss;
protected $jwtAud;
protected $tokenName;
public function __construct()
{
parent::__construct();
$this->key = config('system.jwt_key');
$this->jwtAlgo = config('system.jwt_algo');
$this->jwtIss = config('system.jwt_iss');
$this->jwtAud = config('system.jwt_aud');
$this->tokenName = config('system.token_name');
}
// 获取token的方法(校验用户输入的用户名密码正确后调用,生成token)
public function getToken($info, $idName = 'userId')
{
$jwtExpHour = config('system.jwt_exp_hour');
$time = time();
$payload = [
'iss' => $this->jwtIss,
'aud' => $this->jwtAud,
'iat' => $time,
'nbf' => $time,
'exp' => $time + 3600 * $jwtExpHour,
'username'=>$info['user_name'],
(string)$idName => $info['user_id']
];
$token = JWT::encode($payload, $this->key, $this->jwtAlgo);
return $token;
}
// 校验token的方法(在需要校验token的接口中调用)
public function checkToken($flag = false, $_token = null)
{
// 去掉token中的'Bearer '
$token = !empty($_token) ? $_token : substr(Request::instance()->header($this->tokenName), 7);
if (empty($token))
return ['status' => false, 'msg' => 'token为空'];
try {
$token = think_decrypt($token);
$decoded = JWT::decode($token, new Key($this->key, $this->jwtAlgo));
// 校验token是否为空
if (empty($decoded)) {
return ['status' => false, 'msg' => 'token为空'];
}
// 校验token是否合法
if ($decoded->iss !== $this->jwtIss || $decoded->aud !== $this->jwtAud) {
return ['status' => false, 'msg' => 'token不合法'];
}
// 校验token是否过期
if ($decoded->exp < time()) {
return ['status' => false, 'msg' => 'token已过期'];
}
// 校验token是否正确
if ($decoded->userId === "") {
return ['status' => false, 'msg' => 'token参数为空'];
}
if ($flag) {
return $decoded;
}
return ['status' => true, 'msg' => 'token正确'];
} catch (\Exception $e) {
return ['status' => false, 'msg' => '未知错误' . $e->getMessage()];
}
}
// 获取用户id
public function getUserId()
{
$decoded = $this->checkToken(true);
return $decoded->userId;
}
public function getUserName()
{
$decoded = $this->checkToken(true);
return $decoded->username;
}
}
2.登录验证
(1)在模型SysUserModel.php中添加login方法
public function login($param)
{
$where['user_name'] = ['=', $param['username']];
$info = DataHandle::getOne($this, $where);
if (empty($info))
return ['code' => 500, 'msg' => '帐号不存在!'];
if ($info['del_flag'] == 2)
return ['code' => 500, 'msg' => '帐号已删除!'];
if ($info['status'] > 0)
return ['code' => 500, 'msg' => '帐号已停用!'];
if ($info['password'] != md5($param['password']))
return ['code' => 500, 'msg' => '密码错误! '];
unset($info['password']);
// 添加scope数据权限查询'data_scope'参数
$info['data_scope'] = (new SysRoleModel())->getDataScopeByUserId($info['user_id']);
$token = (new JwtHandle())->getToken($info);
return ['code' => 200, 'msg' => '操作成功', 'token' => think_encrypt($token)];
}
(2)考虑jwt生成token安全性,再次对token进行加解密。在公共common.php加入方法think_encrypt、think_decrypt
/**
* 系统加密方法
* @param string $data 要加密的字符串
* @param string $key 加密密钥
* @param int $expire 过期时间 单位 秒
* @return string
*/
if (!function_exists('think_encrypt')) {
function think_encrypt($data, $key = '', $expire = 0)
{
$key = md5(empty($key) ? config('system.pass_salt') : $key);
$data = base64_encode($data);
$x = 0;
$len = strlen($data);
$l = strlen($key);
$char = '';
for ($i = 0; $i < $len; $i++) {
if ($x == $l) $x = 0;
$char .= substr($key, $x, 1);
$x++;
}
$str = sprintf('%010d', $expire ? $expire + time() : 0);
for ($i = 0; $i < $len; $i++) {
$str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1))) % 256);
}
$str = str_replace(array('+', '/', '='), array('-', '_', ''), base64_encode($str));
return strtoupper(md5($str)) . $str;
}
}
/**
* 系统解密方法
* @param string $data 要解密的字符串 (必须是think_encrypt方法加密的字符串)
* @param string $key 加密密钥
* @return string
*/
if (!function_exists('think_decrypt')) {
function think_decrypt($data, $key = '')
{
$key = md5(empty($key) ? config('system.pass_salt') : $key);
$data = substr($data, 32);
$data = str_replace(array('-', '_'), array('+', '/'), $data);
$mod4 = strlen($data) % 4;
if ($mod4) {
$data .= substr('====', $mod4);
}
$data = base64_decode($data);
$expire = substr($data, 0, 10);
$data = substr($data, 10);
if ($expire > 0 && $expire < time()) {
return '';
}
$x = 0;
$len = strlen($data);
$l = strlen($key);
$char = $str = '';
for ($i = 0; $i < $len; $i++) {
if ($x == $l) $x = 0;
$char .= substr($key, $x, 1);
$x++;
}
for ($i = 0; $i < $len; $i++) {
if (ord(substr($data, $i, 1)) < ord(substr($char, $i, 1))) {
$str .= chr((ord(substr($data, $i, 1)) + 256) - ord(substr($char, $i, 1)));
} else {
$str .= chr(ord(substr($data, $i, 1)) - ord(substr($char, $i, 1)));
}
}
return base64_decode($str);
}
}
更多推荐


所有评论(0)