$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返回值为200,http状态码也是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); } }