Files
CompanyProject/金壶/ydyd_service/application/api/controller/TokenController.php
2024-09-27 01:32:49 +08:00

311 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\api\controller;
use app\api\model\UserModel;
use think\Db;
use think\facade\Cache;
use think\Exception;
/**
* 生成token
*/
class TokenController extends ApiController
{
protected $noAuth = ['login','refresh'];
/**
* 请求时间差
*/
public static $timeDif = 1000000;
public static $accessTokenPrefix = 'accessToken_';
public static $refreshAccessTokenPrefix = 'refreshAccessToken_';
public static $expires = 60*60*24*7; //暂时修改60*60*24*7
public static $refreshExpires = 60*60*24*90; //刷新token过期时间60*60*24*90
/**
* 测试appid正式请数据库进行相关验证
*/
public static $appid = 'test';
/**
* appsercet
*/
public static $appsercet = '123456';
/*获取token*/
public function token($user,$data)
{
$userInfo = [
'id' => $user['user_id'],
'phone' => $user['phone'],
];
try {
$accessToken = self::setAccessToken(array_merge($userInfo,$data));
return $accessToken;
} catch (Exception $e) {
return self::returnMsg(500,'fail',$e);
}
}
/**
* @apiDefine login 活动管理
*/
/**
* @apiVersion 1.0.0
* @api {any} / 1.整体说明(朱晓伟)
* @apiName AAA
* @apiGroup login
* @apiSuccessExample Success-Response:
* 1. 先获取token其他接口在header里面传入authentication
* authentication = USERID base64_encode("appid" + "-" +"uid" + "-" + "access_token" + "-" + "refresh_token") 加密后签名(参数与参数中间需要加上-号)
* 2. 若请求地址中含有“:”,表示这个参数是在请求地址中,如:平台公告详情:/messages/platforms/:id将:id换成不同的值即可获得id对应的公告详情
* 3. 状态码
* 所有接口返回值以实际返回结果为准接口code返回值为200http状态码也是200表示请求成功其他表示请求失败。
* code值说明
* 401登录相关接口验证失败时返回
* 1xxxx传递参数提示
* 2xxxx数据验证提示
* 3xxxx业务提示
* 4. 参数:
* 所有请求参数,除了有“可选”的标记或列表用于搜索的参数外,其余都是必传。
* 5. 分页参数名为page每页展示条数由后台返回
* {
* "code": 200,
* "message": "成功",
* "data": {
* "total": 60, // 总数据量
* "per_page": 10, // 每页数据条数
* "current_page": 1, // 当前页数
* "last_page": 6, // 数据总页数
* "data": [
* {
* "id": 23356,
* ...
* },
* {
* "id": 19244,
* ...
* }
* ]
* }
* }
* 6. 各接口返回的数据中,有注释的字段都是重要或者需要可能有用的字段,未注释字段可不用理会。
* 完善中...
*/
/**
* @apiVersion 1.0.0
* @api {post} /token/login 2.获取token 登录(朱晓伟)
* @apiName login
* @apiGroup login
* @apiParam {String} phone 手机号
* @apiParam {String} password 账号密码
* @apiParam {String} appid
* @apiParam {Integer} timestamp 时间戳
* @apiParam {String} sign 签名($appsercet+$appid+account+md5(password)+时间戳)
* @apiSuccessExample Success-Response:
*{
"code": 200,
"message": "success",
"data": {
"access_token": "GFkw82j36Tbs9JrCi5fA1I7ztmouxeX9",
"expires_time": 1565762455,
"refresh_token": "1xzjD8gJGlSZheH6wKu9pCfRt9rd4IoE",
"refresh_expires_time": 1596693655,
"client": {
"id": 22, //员工ID
"phone": "17610889520", //手机号码
"appid": "tp5restfultest",
"timestamp": 1565157655,
"sign": "11420815e6b79bd3491b3664404b91fe",
}
}
}
* @apiErrorExample Error-Response:
* {
"code": 500,
"message": "fail",
"data": {
"info": "短信验证码错误,请重新获取"
}
}
*/
public function login(){
try {
$params = input('');
self::checkParams($params); //参数校验
$user = Db::name("users")->where('phone',$params['phone'])->find();
$pwd = md5($params['password'].$user['secure_password_key']);
if($pwd != $user['password']){
return self::returnMsg(401,'账号密码有误',[]);
}
$accessToken = self::token($user,$params);
return self::returnMsg(ApiController::SUCCESS, ApiController::getMessage('SUCCESS'),$accessToken);
} catch (Exception $e) {
return self::returnMsg($e->getCode(), $e->getMessage());
}
}
/**
* @apiVersion 1.0.0
* @api {post} /token/refresh 3.刷新token (朱晓伟)
* @apiName refresh
* @apiGroup login
* @apiParam {String} refresh_token 参数说明
* @apiParam {String} appid 参数说明
* @apiSuccessExample Success-Response:
* {
"code": 200,
"message": "成功",
"data": {
"access_token": "1JGKFnYE8N6C2mAvyk9lpSHZoz4WhId8",
"expires_time": 1565852253,
"refresh_token": "1xzjD8gJGlSZheH6wKu9pCfRt9rd4IoE",
"refresh_expires_time": 1596783453,
"client": {
"appid": "tp5restfultest"
}
}
}
*/
public function refresh()
{
$refresh_token = input('refresh_token');
$cache_refresh_token = Cache::get(self::$refreshAccessTokenPrefix.$refresh_token); //查看刷新token是否存在
if(!$cache_refresh_token){
return self::returnMsg(ApiController::ERR_USER_REFRESH_TOKEN_EXPIRE,ApiController::getMessage('ERR_USER_REFRESH_TOKEN_EXPIRE'),[]);
}else{
if($cache_refresh_token['refresh_token'] !== $refresh_token){
return self::returnMsg(ApiController::ERR_USER_TOKEN,ApiController::getMessage('ERR_USER_TOKEN'),[]);
}else{ //重新给用户生成调用token
$accessToken = self::setAccessToken($cache_refresh_token,$refresh_token);
return self::returnMsg(ApiController::SUCCESS, ApiController::getMessage('SUCCESS'),$accessToken);
}
}
}
/**
* 参数检测
*/
public static function checkParams($params = [])
{
//手机号校验
if(!$params['phone']){
throw new Exception('手机号不能为空',401);
}
//密码校验
if(!$params['password']){
throw new Exception('密码不能为空',401);
}
//时间戳校验
if(abs($params['timestamp'] - time()) > self::$timeDif){
throw new Exception('登录验证异常',401);//'timestamp'.time()
}
//appid检测这里是在本地进行测试正式的应该是查找数据库或者redis进行验证
if($params['appid'] !== self::$appid){
throw new Exception('登录验证异常',401);
}
//签名检测
$sign = OauthController::makeSign($params,self::$appsercet);
if($sign !== $params['sign']){
throw new Exception('登录验证异常',401);
}
}
/**设置AccessToken
* @param $clientInfo
* @param null $refresh_token
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
protected function setAccessToken($clientInfo,$refresh_token = null)
{
//生成令牌
unset($clientInfo['password']);
$accessToken = self::buildAccessToken();
if(!$refresh_token){
$refresh_token = self::buildAccessToken();
}else{
$refresh = self::getRefreshTokenInfo($refresh_token);
$clientInfo = $refresh['client'];
}
$accessTokenInfo = [
'access_token' => $accessToken,//访问令牌
'expires_time' => time() + self::$expires, //过期时间时间戳
'refresh_token' => $refresh_token,//刷新的token
'refresh_expires_time' => time() + self::$refreshExpires, //过期时间时间戳
'client' => $clientInfo,//用户信息
];
self::saveAccessToken($accessToken, $accessTokenInfo); //保存本次token
self::saveRefreshToken($refresh_token,$accessTokenInfo); //保存本次refresh_token
$res = UserModel::field('access_token,refresh_token')->where(['user_id'=>$clientInfo['id']])->find();//查询用户token refresh_token
if($res){//如果存在 则清除之前的缓存
Cache::rm(self::$accessTokenPrefix.$res['access_token']);
Cache::rm(self::$refreshAccessTokenPrefix.$res['refresh_token']);
Cache::rm('USER_INFO_API'.$clientInfo['id']);
}
UserModel::update(['access_token'=>$accessToken,'refresh_token'=>$refresh_token],['user_id'=>$clientInfo['id']]);//保存token和refresh_token到数据库用于单点登录
return $accessTokenInfo;
}
/**
* 刷新用的token检测是否还有效
*/
public static function getRefreshToken($appid = '')
{
$token = Cache::get(self::$refreshAccessTokenPrefix.$appid);
return $token ? $token['refresh_token'] : self::buildAccessToken();
}
/**
* 刷新用的token检测是否还有效
*/
public static function getRefreshTokenInfo($refresh_token)
{
$refresh = Cache::get(self::$refreshAccessTokenPrefix.$refresh_token);
return $refresh ? $refresh : '';
}
/**
* 生成AccessToken
* @return string
*/
protected static function buildAccessToken($lenght = 32)
{
//生成AccessToken
$str_pol = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789abcdefghijklmnopqrstuvwxyz";
return substr(str_shuffle($str_pol), 0, $lenght);
}
/**
* 存储token
* @param $accessToken
* @param $accessTokenInfo
*/
protected static function saveAccessToken($accessToken, $accessTokenInfo)
{
//存储accessToken
Cache::set(self::$accessTokenPrefix . $accessToken, $accessTokenInfo, self::$expires);
}
/**
* 存储refreshToken
* @param $refresh_token
* @param $accessTokenInfo
*/
protected static function saveRefreshToken($refresh_token,$accessTokenInfo)
{
//存储RefreshToken
Cache::set(self::$refreshAccessTokenPrefix.$refresh_token, $accessTokenInfo,self::$refreshExpires);
}
}