企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## 一,安装firebase/php-jwt扩展: 1,命令: ~~~ liuhongdi@lhdpc:/data/php/admapi$ composer require firebase/php-jwt ~~~ 2,安装成功后的位置: ![](https://img.kancloud.cn/7b/b5/7bb5b79cec30773a8ddf6b66291ac003_352x390.png) 3,查看firebase/php-jwt的版本: ~~~ liuhongdi@lhdpc:/data/php/admapi$ composer show firebase/php-jwt ~~~ ![](https://img.kancloud.cn/d4/e0/d4e01e6a9217c6bf404c22b1f7ae28a6_1225x494.png) ## 二,前端vue代码: Login.vue ~~~ <template> <div style="padding:20px;display: flex;align-items:center;justify-content: center;"> <form :model="account" style="margin-top:50px;width:400px;"> <input v-model="account.username" placeholder="请输入用户名" style="width:392px;font-size:16px;" /><br/> <input v-model="account.password" type="password" placeholder="请输入密码" style="width:392px;margin-top:10px;font-size:16px;" /><br/> <!--v-loading.fullscreen.lock="isLoading"--> <div @click="login" style="margin-top:10px;width: 100%;height:40px;line-height:40px;background: #ff0000;border-radius: 10px;"> 登录 </div> <div @click="info" style="margin-top:10px;width: 100%;height:40px;line-height:40px;background: #ff0000;border-radius: 10px;"> info </div> <div class="text-align-right"> </div> </form> </div> </template> <script> import { ref, reactive } from "vue"; import { ElMessage } from "element-plus"; import { apiLogin,apiInfo,apiToken} from '@/api/api'; export default { name: "Login", setup() { const accountRef = ref(null); //表单字段 const account = reactive({ username: "", password: "", }); //登录 const login = async () => { console.log('begin login'); var data = new FormData(); data.append("username",account.username); data.append("password",account.password); apiLogin(data).then(res => { //成功 if (res.code == 0) { //保存jwt token到本地 localStorage.setItem('token', res.data.token); //提示 ElMessage.success("登录成功!"); } else { ElMessage.error("登录失败:"+res.msg); } }).catch((error) => { console.log(error) }) }; const login2 = () => { console.log('begin login2'); } const info = () => { apiInfo().then(res => { //成功 if (res.code == 0) { //保存jwt token到本地 //localStorage.setItem('token', res.data.token); //提示 //ElMessage.success("登录成功!"); console.log(res.data); } else { ElMessage.error("用户信息获取失败:"+res.msg); } }).catch((error) => { console.log(error) }) } return { account, //loginRules, accountRef, login, login2, info, //isLoading, }; }, } </script> <style scoped> </style> ~~~ api/axios.js ``` ... //post export function postForm (url, params) { return new Promise((resolve, reject) => { let headers = { 'Content-Type': 'application/x-www-form-urlencoded', } //判断params中是否包含X-CSRF-TOKEN var token = ""; if (params.has("X-CSRF-TOKEN")) { token = params.get("X-CSRF-TOKEN"); params.delete("X-CSRF-TOKEN"); headers = { 'Content-Type': 'application/x-www-form-urlencoded', 'X-CSRF-TOKEN': token, } } _axios.post(url, params,{headers}) .then(res => { resolve(res.data) }) .catch(err => { console.log("api error:"); console.log(err); //alert(err); reject(err.data) }) }) } ... ``` api/api.js ``` //get, import { get, postForm} from './axios' //user export const apiLogin = pLogin => postForm('/api/auth/login', pLogin) ... ``` ## 三,后端php代码: 1,创建middleware ~~~ liuhongdi@lhdpc:/data/php/admapi$ php think make:middleware CheckJwt Middleware:app\middleware\CheckJwt created successfully.  ~~~ 2,CheckJwt的代码:  ~~~ <?php declare (strict_types = 1); namespace app\middleware; use app\lib\util\JwtUtil; class CheckJwt { /** * 处理请求,得到用户信息 * * @param \think\Request $request * @param \Closure $next * @return Response */ public function handle($request, \Closure $next) { $auth = $request->header('authorization'); if ($auth == null) { return $next($request); } $token = str_replace("Bearer ","",$auth); $jUtil = new JwtUtil(); $res = $jUtil->verifyjwt($token); if (isset($res['code']) && isset($res['userId']) && $res['code'] == 0 && is_int($res['userId'])) { $userId = $res['userId']; $request->auth = $userId; } else { $request->auth = 0; } return $next($request); } } ~~~ 3,app/middleware.php 使从jwt得到用户信息的middleware生效: ~~~ <?php // 全局中间件定义文件 return [ app\middleware\CheckJwt::class, ]; ~~~ 4,controller/Auth.php ~~~ <?php declare (strict_types = 1); namespace app\controller; use app\BaseController; use think\facade\Cache; use think\Request; use app\result\Result; use think\response\Json; use app\validate\Login as LoginValidate; use app\validate\GoodsList as GoodsListValidate; use think\exception\ValidateException; use app\lib\util\JwtUtil; class Auth extends BaseController { /* *得到form token * *@return \think\Response * */ public function token():Json { $type="sha1"; $type = is_callable($type) ? $type : 'md5'; $token = call_user_func($type, $this->request->server('REQUEST_TIME_FLOAT')); $key = uniqid(); Cache::set($key,$token,300); $res = [ "token"=>$key.$token, ]; return Result::Success($res); } /** * 登录 * * @return \think\Response */ public function login():Json { // Header验证 if ($this->request->header('X-CSRF-TOKEN')){ $reqToken = $this->request->header('X-CSRF-TOKEN'); $key = substr($reqToken,0,13); $value = Cache::get($key); $origToken = $key.$value; if ($origToken === $reqToken) { //验证通过 } else { //验证不通过 return Result::Error(422,'表单token错误'); } } else { return Result::Error(423,'找不到表单token'); } try { validate(LoginValidate::class) ->check($_POST); } catch (ValidateException $e) { // 验证失败 输出错误信息 return Result::Error(422,$e->getError()); } if ($_POST["username"] == "dddddd" && $_POST["password"] == "111111"){ //验证成功,生成jwt返回 $userId = 123; $jUtil = new JwtUtil(); $token = $jUtil->createJwt($userId); $res = ["token"=>$token]; // 防止重复提交 Cache::delete($key); return Result::Success($res); } else { return Result::Error(422,"用户名密码错误"); } } } ~~~ Result.php ``` <?php namespace app\result; use think\response\Json; class Result { //success static public function Success($data):Json { $rs = [ 'code'=>0, 'msg'=>"success", 'data'=>$data, ]; return json($rs); } //error static public function Error($code,$msg):Json { $rs = [ 'code'=>$code, 'msg'=>$msg, 'data'=>"", ]; return json($rs); } } ``` 5,lib/util/JwtUtil.php ~~~ <?php namespace app\lib\util; use Firebase\JWT\ExpiredException; use Firebase\JWT\JWT; class JwtUtil { private $signKey = "lhd@2001:liuhongdi"; private $timeMinutes = 5; /** * 根据json web token设置的规则生成token * @return \think\response\Json */ public function createJwt($userId):string { $key = md5($this->signKey); //jwt的签发**,验证token的时候需要用到 $time = time(); //签发时间 $expire = $time + $this->timeMinutes*60; //过期时间 $token = array( "userId" => $userId, "iss" => "http://www.liuhongdi.com/",//签发组织 "aud" => "lhd", //签发作者 "iat" => $time, //签发时间 "nbf" => $time, //生效时间 "exp" => $expire //过期时间 ); $jwt = JWT::encode($token,$key); return $jwt; } /** * 验证token * @return \think\response\Json */ public function verifyjwt($token) { $key = md5($this->signKey); //jwt的签发**,验证token的时候需要用到 try{ $jwtAuth = json_encode(JWT::decode($token,$key,array("HS256"))); $authInfo = json_decode($jwtAuth,true); if (!$authInfo['userId']){ return ['code'=>0,'msg'=>"用户不存在"]; } return ['code'=>0,'userId'=>$authInfo['userId'],'msg'=>"ok"]; }catch (ExpiredException $e){ return ['code'=>0,'msg'=>"token过期"]; }catch (\Exception $e){ return ['code'=>0,'msg'=>$e->getMessage()]; } } } ~~~ ## 四,效果测试 1,界面:用户名 dddddd,密码;111111,可见php的代码: ![](https://img.kancloud.cn/a5/5c/a55cd0926c973d019e143bd091b2c7ee_1364x694.png) 2,未登录时点info ![](https://img.kancloud.cn/6d/11/6d1114cbca7f177aefdc1b31bc669ebd_1284x588.png) 3,登录后的返回: ![](https://img.kancloud.cn/49/29/49291e5417d8d37744f1fdc512349b6f_1262x554.png) 4,登录后查看info的返回: ![](https://img.kancloud.cn/3d/28/3d28221bb29da63439be2cb264340883_1274x524.png)