zoukankan      html  css  js  c++  java
  • thinkphp6: 前后端分离:用jwt+middleware做用户登录验证(php 8.1.1 / thinkphp v6.0.10LTS )

    一,安装firebase/php-jwt扩展:

    1,命令:
    liuhongdi@lhdpc:/data/php/admapi$ composer require firebase/php-jwt
    2,安装成功后的位置:
    3,查看firebase/php-jwt的版本:
    liuhongdi@lhdpc:/data/php/admapi$ composer show firebase/php-jwt

    说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

             对应的源码可以访问这里获取: https://github.com/liuhongdi/
             或: https://gitee.com/liuhongdi

    说明:作者:刘宏缔 邮箱: 371125307@qq.com

    二,前端vue代码:

    Login.vue

    <template>
      <div style="padding:20px;display: flex;align-items:center;justify-content: center;">
        <form :model="account"  style="margin-top:50px;400px;">
            <input v-model="account.username" placeholder="请输入用户名" style="392px;font-size:16px;" /><br/>
            <input v-model="account.password"  type="password" placeholder="请输入密码" style="392px;margin-top:10px;font-size:16px;" /><br/>
            <!--v-loading.fullscreen.lock="isLoading"-->
            <div    @click="login"  style="margin-top:10px; 100%;height:40px;line-height:40px;background: #ff0000;border-radius: 10px;">
              登录
            </div>
          <div    @click="info"  style="margin-top:10px; 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>

    三,后端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
    {
        /**
         * 登录
         *
         * @return \think\Response
         */
        public function login():Json {
            try {
                validate(LoginValidate::class)
                    //->scene('edit')
                    ->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,"用户名密码错误");
            }
        }
        /**
         * 得到用户信息
         *
         * @return \think\Response
         */
        public function info()
        {
            if ($this->request->auth > 0) {
                $status = "已登录";
            } else {
                $status = "未登录";
            }
    
            $info = [
                'userId'=>$this->request->auth,
                'status'=>$status,
            ];
            return Result::Success($info);
        }
    }

    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的代码:

    2,未登录时点info

    3,登录后的返回:

    4,登录后查看info的返回:

    五,查看php和thinkphp的版本:

    php:
    liuhongdi@lhdpc:/data/php/admapi$ php --version
    PHP 8.1.1 (cli) (built: Dec 20 2021 16:12:16) (NTS)
    Copyright (c) The PHP Group
    Zend Engine v4.1.1, Copyright (c) Zend Technologies
        with Zend OPcache v8.1.1, Copyright (c), by Zend Technologies 
    thinkphp:
    liuhongdi@lhdpc:/var/www/html$ cd /data/php/admapi/
    liuhongdi@lhdpc:/data/php/admapi$ php think version
    v6.0.10LTS 
  • 相关阅读:
    微信开发(5):公众号消息与事件推送处理(转)
    微信开发(4):微信第三方开放平台的搭建(转)
    微信开发(3):微信公众号发现金红包功能开发,利用第三方SDK实现(转)
    微信开发(2):微信js sdk分享朋友圈,朋友,获取config接口注入权限验证(转)
    微信开发(1) :网页授权获取用户的基本信息 实现微信登录(转)
    java实现创建临时文件然后在程序退出时自动删除文件(转)
    Linux定时对日志批量打包Shell脚本及定时任务crontab 详细用法
    httpd2.4出现AH00025: configuration error
    apache启动失败
    软件工程中的反面模式(anti-pattern)
  • 原文地址:https://www.cnblogs.com/architectforest/p/15776999.html
Copyright © 2011-2022 走看看