From ea577de1e633de886a51796660b3849148390bb4 Mon Sep 17 00:00:00 2001 From: vilson <545522390@qq.com> Date: Tue, 29 Jan 2019 18:13:18 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8E=A5=E5=85=A5JWT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: vilson <545522390@qq.com> --- application/common/Model/ProjectMenu.php | 3 +- application/index/controller/Index.php | 16 +++ application/project/common.php | 17 +++ application/project/controller/Account.php | 8 +- application/project/controller/Index.php | 4 +- application/project/controller/Login.php | 8 +- application/project/middleware/Auth.php | 26 +++-- composer.json | 3 +- config/jwt.php | 16 +++ extend/service/JwtService.php | 118 +++++++++++++++++++++ extend/service/NodeService.php | 14 ++- extend/service/SessionService.php | 53 --------- 12 files changed, 212 insertions(+), 74 deletions(-) create mode 100644 config/jwt.php create mode 100644 extend/service/JwtService.php delete mode 100644 extend/service/SessionService.php diff --git a/application/common/Model/ProjectMenu.php b/application/common/Model/ProjectMenu.php index e287d12..05fe665 100644 --- a/application/common/Model/ProjectMenu.php +++ b/application/common/Model/ProjectMenu.php @@ -82,7 +82,8 @@ class ProjectMenu extends CommonModel } } //主账号不做过滤 - $menus = session('member.is_owner') ? $list : $this->filterMenu($list, session('member.nodes')); + $member = getCurrentMember(); + $menus = $member['is_owner'] ? $list : $this->filterMenu($list, $member['nodes']); $new = []; $this->buildFilterMenuData(ToolsService::arr2tree($menus), $new); $menus = ToolsService::arr2tree($new); diff --git a/application/index/controller/Index.php b/application/index/controller/Index.php index 77ffc3e..2fbfbcf 100644 --- a/application/index/controller/Index.php +++ b/application/index/controller/Index.php @@ -23,7 +23,9 @@ use app\common\Model\TaskMember; use app\common\Model\TaskStages; use controller\BasicApi; use Exception; +use Firebase\JWT\JWT; use PDO; +use service\JwtService; use service\MessageService; use think\facade\Request; @@ -193,6 +195,20 @@ class Index extends BasicApi TaskStages::where("id > 0")->delete(); } + /** + *刷新token + */ + public function refreshAccessToken() + { + $refreshToken = Request::param('refreshToken', ''); + $data = JwtService::decodeToken($refreshToken); + if (isError($data)) { + $this->error('token过期,请重新登录', 401); + } + $this->success('', JwtService::getAccessToken(get_object_vars($data->data))); + + } + /** * 获取行政区划数据 */ diff --git a/application/project/common.php b/application/project/common.php index 5881c81..f8e4f72 100644 --- a/application/project/common.php +++ b/application/project/common.php @@ -35,18 +35,35 @@ function _uploadFile(File $file, $path_name = '', $saveName = false) return false; } + + function getCurrentMember() { return session('member'); } +function setCurrentMember($data) +{ + return session('member', $data); +} + function getCurrentOrganizationCode() { return session('currentOrganizationCode'); } +function setCurrentOrganizationCode($data) +{ + return session('currentOrganizationCode', $data); +} + function getCurrentOrganization() { return session('organization'); } +function setCurrentOrganization($data) +{ + return session('organization', $data); +} + diff --git a/application/project/controller/Account.php b/application/project/controller/Account.php index 726ae94..cafed23 100644 --- a/application/project/controller/Account.php +++ b/application/project/controller/Account.php @@ -179,10 +179,12 @@ class Account extends BasicApi } else { unset($params['password']); } + $member = getCurrentMember(); + $currentOrganizationCode = getCurrentOrganizationCode(); $params['create_time'] = nowTime(); - $params['member_code'] = session('member.code'); - $params['organization_code'] = session('currentOrganizationCode'); - $user = $this->model->where(['account' => $params['account'], 'member_code' => session('member.code'), 'organization_code' => session('currentOrganizationCode')])->find(); + $params['member_code'] = $member['code']; + $params['organization_code'] = $currentOrganizationCode; + $user = $this->model->where(['account' => $params['account'], 'member_code' => $member['code'], 'organization_code' => $currentOrganizationCode])->find(); $user && $this->error("该账号已存在!"); $result = $this->model->_add($params); if ($result) { diff --git a/application/project/controller/Index.php b/application/project/controller/Index.php index 38eb4eb..d0ee5bf 100644 --- a/application/project/controller/Index.php +++ b/application/project/controller/Index.php @@ -48,9 +48,9 @@ class Index extends BasicApi $member['account_id'] = $memberAccount['id']; $member['is_owner'] = $memberAccount['is_owner']; $member['authorize'] = $memberAccount['authorize']; - session('member', $member); + setCurrentMember($member); !empty($member['authorize']) && NodeService::applyProjectAuthNode(); - session('currentOrganizationCode', $organizationCode); + setCurrentOrganizationCode($organizationCode); $list = MemberAccount::getAuthMenuList(); $this->success('', $list); diff --git a/application/project/controller/Login.php b/application/project/controller/Login.php index ab10a2c..4e8ca1e 100644 --- a/application/project/controller/Login.php +++ b/application/project/controller/Login.php @@ -5,6 +5,7 @@ namespace app\project\controller; use app\common\Model\Member; use app\common\Model\Organization; use controller\BasicApi; +use service\JwtService; use service\LogService; use service\NodeService; use service\RandomService; @@ -97,10 +98,13 @@ class Login extends BasicApi $member['position'] = $list[0]['position']; $member['department'] = $list[0]['department']; - session('member', $member); + setCurrentMember($member); !empty($member['authorize']) && NodeService::applyProjectAuthNode(); Log::write(json_encode($member), "member-login"); - $this->success('', ['member' => $member, 'organizationList' => $organizationList]); + $tokenList = JwtService::initToken($member); + $accessTokenExp = JwtService::decodeToken($tokenList['accessToken'])->exp; + $tokenList['accessTokenExp'] = $accessTokenExp; + $this->success('', ['member' => $member, 'tokenList' => $tokenList, 'organizationList' => $organizationList]); } public function getCaptcha() diff --git a/application/project/middleware/Auth.php b/application/project/middleware/Auth.php index c9feeb4..648f13a 100644 --- a/application/project/middleware/Auth.php +++ b/application/project/middleware/Auth.php @@ -3,9 +3,8 @@ namespace app\project\middleware; use app\common\Model\ProjectNode; +use service\JwtService; use service\NodeService; -use think\facade\Response; -use think\facade\Session; use think\Request; /** @@ -29,14 +28,27 @@ class Auth $access = $this->buildAuth($node = NodeService::parseNodeStr("{$module}/{$controller}/{$action}")); $currentOrganizationCode = $request->header('organizationCode'); if ($currentOrganizationCode) { - session('currentOrganizationCode', $currentOrganizationCode); + setCurrentOrganizationCode($currentOrganizationCode); } + $authorization = $request->header('Authorization'); + $accessToken = ''; + if ($authorization) { + $accessToken = explode(' ', $authorization)[1]; + } + $data = JwtService::decodeToken($accessToken); // 登录状态检查 - if (!empty($access['is_login']) && !session('member')) { - $msg = ['code' => 401, 'msg' => '抱歉,您还没有登录获取访问权限!']; - return json($msg); + if (!empty($access['is_login'])) { + $isError = isError($data); + if ($isError) { + if ($data['errno'] == 3) { + $msg = ['code' => 4010, 'msg' => 'accessToken过期']; + return json($msg); + } + $msg = ['code' => 401, 'msg' => 'token过期,请重新登录']; + return json($msg); + } + setCurrentMember(get_object_vars($data->data)); } - // 访问权限检查 if (!empty($access['is_auth']) && !auth($node, 'project')) { return json(['code' => 403, 'msg' => '无权限操作资源,访问被拒绝']); diff --git a/composer.json b/composer.json index 9ef26a3..edc3a8e 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,8 @@ "workerman/gateway-worker-for-win" : ">=3.0.0", "workerman/gateway-worker" : ">=3.0.0", "overtrue/easy-sms": "^1.1", - "phpoffice/phpspreadsheet": "^1.5" + "phpoffice/phpspreadsheet": "^1.5", + "firebase/php-jwt": "^5.0" }, "autoload": { "psr-4": { diff --git a/config/jwt.php b/config/jwt.php new file mode 100644 index 0000000..f0a6d6f --- /dev/null +++ b/config/jwt.php @@ -0,0 +1,16 @@ + 'pearProject', + 'alg' => 'HS256', + //access_token有效时间 + 'accessTokenExp' => 20, + //refresh_token有效时间 + 'refreshTokenExp' => 3600 * 24 * 7, + //签发者 可选 + 'iss' => '', + //接收该JWT的一方,可选 + 'aud' => '', + 'tokenType' => 'bearer', +]; diff --git a/extend/service/JwtService.php b/extend/service/JwtService.php new file mode 100644 index 0000000..2749962 --- /dev/null +++ b/extend/service/JwtService.php @@ -0,0 +1,118 @@ + $jwtConfig['iss'], + "aud" => $jwtConfig['aud'], + "iat" => $time, + "nbf" => $time, + ); + return $token; + } + + /** + * 创建初始token + * @param $data + * @return array 返回accessToken 和 refreshToken + */ + public static function initToken($data) + { + $tokenList = [ + 'accessToken' => self::getAccessToken($data), + 'refreshToken' => self::getRefreshToken($data), + 'tokenType' => config('jwt.tokenType') //token_type:表示令牌类型,该值大小写不敏感,这里用bearer + ]; + return $tokenList; + } + + /** + * 获取accessToken + * @param $data + * @return string + */ + public static function getAccessToken($data) + { + $accessToken = self::getCommonConfig(); + $jwtConfig = config('jwt.'); + $key = $jwtConfig['key']; + $time = time(); + $accessToken['data'] = $data; + $accessToken['scopes'] = 'access'; + $accessToken['exp'] = $time + $jwtConfig['accessTokenExp']; + return JWT::encode($accessToken, $key, $jwtConfig['alg']); + } + + /** + * 获取refreshToken + * @param $data + * @return string + */ + public static function getRefreshToken($data) + { + $refreshToken = self::getCommonConfig(); + $jwtConfig = config('jwt.'); + $key = $jwtConfig['key']; + $time = time(); + $refreshToken['data'] = $data; + $refreshToken['scopes'] = 'refresh'; + $refreshToken['exp'] = $time + $jwtConfig['refreshTokenExp']; + return JWT::encode($refreshToken, $key, $jwtConfig['alg']); + } + + + /** + * 根据refreshToken刷新accessToken + * @param $refreshToken + * @return array|object|string + */ + public static function refreshAccessToken($refreshToken) + { + $decoded = self::decodeToken($refreshToken); + if (isError($decoded)) { + return $decoded; + } + return self::getAccessToken($decoded['data']); + } + + /** + * token解密 + * @param $token + * @return array|object + */ + public static function decodeToken($token) + { + $jwtConfig = config('jwt.'); + JWT::$leeway = 60;//当前时间减去60,把时间留点余地 + try { + $decoded = JWT::decode($token, $jwtConfig['key'], array($jwtConfig['alg']));//解密方式,这里要和签发的时候对应 + } catch (\Firebase\JWT\SignatureInvalidException $e) { //签名不正确 + return error(1, $e->getMessage()); + } catch (\Firebase\JWT\BeforeValidException $e) { // 签名在某个时间点之后才能用 + return error(2, $e->getMessage()); + } catch (\Firebase\JWT\ExpiredException $e) { // token过期 + return error(3, $e->getMessage()); + } catch (\Exception $e) { //其他错误 + return error(4, $e->getMessage()); + } + return $decoded; + } + +} diff --git a/extend/service/NodeService.php b/extend/service/NodeService.php index 460bb0f..34431ee 100644 --- a/extend/service/NodeService.php +++ b/extend/service/NodeService.php @@ -20,14 +20,17 @@ class NodeService public static function applyProjectAuthNode() { cache('member_need_access_node', null); - if (($authorize = session('member.authorize'))) { + $member = getCurrentMember(); + if (($authorize = $member['authorize'])) { $where = ['status' => '1']; $authorizeIds = Db::name('ProjectAuth')->whereIn('id', explode(',', $authorize))->where($where)->column('id'); if (empty($authorizeIds)) { - return session('member.nodes', []); + $member['nodes'] = []; + return setCurrentMember($member); } $nodes = Db::name('ProjectAuthNode')->whereIn('auth', $authorizeIds)->column('node'); - return session('member.nodes', $nodes); + $member['nodes'] = $nodes; + return setCurrentMember($member); } return false; } @@ -56,15 +59,16 @@ class NodeService { list($module, $controller, $action) = explode('/', str_replace(['?', '=', '&'], '/', $node . '///')); $currentNode = self::parseNodeStr("{$module}/{$controller}") . strtolower("/{$action}"); + $member = getCurrentMember(); if ($moduleApp == 'project') { //拥有者账号不加入权限判断 - if (session('member.is_owner') == 1) { + if ($member['is_owner'] == 1) { return true; } if (!in_array($currentNode, self::getProjectAuthNode())) { return true; } - return in_array($currentNode, (array)session('member.nodes')); + return in_array($currentNode, (array)$member['nodes']); } return false; } diff --git a/extend/service/SessionService.php b/extend/service/SessionService.php deleted file mode 100644 index 5987d8d..0000000 --- a/extend/service/SessionService.php +++ /dev/null @@ -1,53 +0,0 @@ -