搜索
首页后端开发PHP问题php如何设置权限令牌token

php如何设置权限令牌token

Aug 20, 2020 am 10:13 AM
phptoken

php设置token的方法:1、定义获取Token的路由路径;2、建立Service层;3、使用UserToken类处理整个逻辑;4、在Model层里建立User类;5、在验证器类和异常类创建相应的验证方法和异常处理。

php如何设置权限令牌token

推荐:《PHP视频教程

PHP_设置权限令牌Token

我们开发的后端API接口会对访问者有一个权限要求,比如一些包含私人信息的接口,就需要访问者请求接口的同时,传递一个提前已经发放给访问者的Token。

这就像一个令牌一样,只有访问者展示出来我们才会“通过放行”。

下面就记录一下权限令牌的代码编写思路。


一、流程概要

  • 定义获取Token的路由路径,接受code参数(code来源:微信服务器,登录系统基于微信体系)

  • 建立Service层,在这层里创建Token基类和UserToken类

  • UserToken类处理整个逻辑:Token生成和返回

  • 在Model层里建立User类,负责用户数据表的读写,供Service层的UserToken调用

  • 在验证器类和异常类创建相应的验证方法和异常处理

  • 控制器->Service层->Model层返回值给Service层->Service层返回值给控制器,整个流程完成Token令牌的编写

二、具体说明

首先定义好路由路径:

Route::post(
    'api/:version/token/user',
    'api/:version.Token/getToken'
);

然后创建Token控制器,定义对应路由路径的getToken方法:

public function getToken($code='') {
        (new TokenGet())->goCheck($code); // 验证器
        $token = (new UserToken($code))->get();
        return [
            'token' => $token
        ];
    }

在调用Service层之前,还得检查一下传递过来的参数,于是定义TokenGet这个验证器:

class TokenGet extends BaseValidate
{
    protected $rule = [
      'code' => 'require|isNotEmpty'
    ];

    protected $message = [
        'code' => '需要code才能获得Token!'
    ];
 }

回到Token控制器,验证通过后,我们调用Service层定义的UserToken类:

$token = (new UserToken($code))->get();复制代码

这里讨论一下Service层和Model层。我们普遍的理解是Service层是基于Model层的一次抽象封装。

  • Model层只负责操作数据库并返且返回给Service层
  • 然后Service层处理业务逻辑,最后返回给Controller层

但我觉得小项目的话,Service其实和Model就有点平级的意思,因为有些简单的接口Model层直接对接Controller就可以了,只有相对复杂的接口,比如用户权限,就可以再经过Service层分隔不同功能的代码。

这样的处理更加灵活,有大量确实很简单的接口就不用过一次Service层了,这样更像是走过过场而已,没什么意义了。

回到Service层的代码编写,由于Token还会有不同的种类,所以先创建一个Token基类,里面包含一些通用的方法。然后就是给访问者返回令牌的UserToken类的编写了。

由于是基于微信,我们需要三个信息:code,appid,appsecret,然后通过构造函数来给UserToken类赋上初始值:

function __construct($code) {
    $this->code = $code;
    $this->wxAppID = config('wx.app_id');
    $this->wxAppSecret = config('wx.app_secret');
    $this->wxLoginUrl = sprintf(
        config('wx.login_url'),
        $this->wxAppID, $this->wxAppSecret, $this->code
    );
    }

然后把这三个放入微信提供的接口的参数位置,目的是获得一个完整的微信服务器端的url,请求到我们需要的openid。

然后是通过发送网络请求的步骤就在此略过。微信服务器会返回包含openid的对象,判断这个对象的值没问题后,我们就开始生成令牌的步骤了,创建函数grantToken():

private function grantToken($openidObj) {

        // 取出openid
        $openid = $openidObj['openid'];
        
        // 通过Model层调用数据库,检查openid是否已经存在
        $user = UserModel::getByOpenID($openid);
        
        // 如果存在,不处理,反之则新增一条user记录
        if ($user) {
            $uid = $user->id;
        } else {
            // 不存在,生成一条数据,具体方法略过
            $uid = $this->newUser($openid); 
        }
        
        // 生成令牌,写入缓存(具体方法见下面的定义)
        $cachedValue = $this->prepareCacheValue($openidObj, $uid);
        $token = $this->saveToCache($cachedValue);
        
        // 令牌返回到调用者端
        return $token;
}

private function prepareCacheValue($openidObj, $uid) {
    $cachedValue = $openidObj;
    $cachedValue['uid'] = $uid;
    $cachedValue['scope'] = 16; // 权限值,自己定义
    return $cachedValue;
}
    
private function saveToCache($cachedValue) {
    $key = self::generateToken(); // 生成令牌的方法
    $value = json_encode($cachedValue);
    $tokenExpire = config('setting.token_expire'); // 设定的过期时间

    $request = cache($key, $value, $tokenExpire);
        if (!$request) {
            throw new TokenException([
            'msg' => '服务器缓存异常',
            'errorCode' => 10005
        ]);
    }
    return $key; // 返回令牌:token
}

可以看到,核心流程就是:

  • 拿到openid
  • 查看数据库,检查openid是否已经存在
  • 如果存在,不处理,反之则新增一条user记录
  • 生成令牌,准备缓存数据,写入缓存
  • 把令牌返回到客户端去

其中generateToken()这个方法详细定义如下:

public static function generateToken() {
    $randomChars = getRandomChars(32); // 32个字符组成一组随机字符串
    $timestamp = $_SERVER['REQUEST_TIME_FLOAT'];  
    $salt = config('security.token_salt'); // salt 盐
    // 拼接三组字符串,进行MD5加密,然后返回
    return md5($randomChars.$timestamp.$salt);
}
    
function getRandomChars($length) {
    $str = null;
    $strPoll = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $max = strlen($strPoll) - 1;

    for ($i = 0; $i < $length; $i++) {
        $str .= $strPoll[rand(0, $max)];
    }
    return $str;
}

它的主要作用毫无疑问就是生成我们的需要的令牌——Token字符串。值得一提的是由于generateToken()在其他类型的Token里也会用到,所以是放在Token基类里的。

至此,只需要把生成的令牌再返回到Controller就行了。

三、总结

令牌的编写涉及到很多的流程,为了避免混乱,一定要注意把负责不同工作的代码分别定义在不同的方法里。就像上面例子里grantToken()方法体现的那样,这是个核心方法,包含所有流程,但是不同的具体流程又定义在其他方法里,然后提供给grantToken()方法调用。

这样做之后grantToken()方法即使包含所有流程,但也依然很容易阅读。

以上是php如何设置权限令牌token的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器