2024年Go最新TP6+JWT开发APP接口_tp6 session和jwt 交互(2),Golang面试基础题

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

composer require lcobucci/jwt

在app/common/auth文件下, 创建JWT封装类库文件

<?php
/\*\*
 \* 老王
 \*
 \*\*/

namespace app\common\lib\auth;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\ValidationData;

/\*\*
 \* 单例模式
 \* 一次请求中所有使用到jwt的地方都是一个用户
 \* Class JwtAuth
 \* @package app\common\lib\auth
 \* 1. 接口鉴权
 \* 2. 获取用户身份
 \*/
class JwtAuth
{
    /\*\*
 \* @var
 \*/
    private $token;
    /\*\*
 \* @var
 \*/
    private $decodeToken;
    /\*\*
 \* claim iss
 \* @var string
 \*/
    private $iss = 'chao.com';
    /\*\*
 \* claim aud
 \* @var string
 \*/
    private $aud = 'tp6\_server\_app';
    /\*\*
 \* 身份 uid
 \* @var string
 \*/
    private $uid;

    /\*\*
 \* @var string
 \*/
    private $secret = 'TP6&\*chao1992#$LJL\*&^&\*9089';

    /\*\*
 \* @var null
 \*/
    private static $instance = null;
    /\*
 \* 私有化 构造函数
 \*/
    private function \_\_construct()
    {
    }
    /\*
 \*
 \*/
    private function \_\_clone()
    {
        // TODO: Implement \_\_clone() method.
    }

    /\*\*
 \* 单例模式 获取jwtAuth句柄
 \* @return JwtAuth|null
 \*/
    public static function getInstance()
    {
        if (is\_null(self::$instance)){
            self::$instance = new self();
        }

        return self::$instance;
    }

    /\*\*
 \* @param $uid
 \* @return $this
 \* 设置身份信息
 \*/
    public function setUid($uid){
        $this->uid = $uid;
        return $this;
    }

    /\*\*
 \* @param $token
 \* 设置token
 \*/
    public function setToken($token){
        $this->token = $token;
        return $this;
    }
    /\*\*
 \* @param $token
 \*/
    public function decode(){

        if (!$this->decodeToken){
            // 把字符串转成Token对象
            $this->decodeToken = (new Parser())->parse((string)$this->token);
            $this->uid = $this->decodeToken->getClaim('uid');
        }

        return $this->decodeToken;
    }

    /\*\*
 \* 校验signature, 判断token是否过期或者被篡改
 \* @return bool
 \*/
    public function verify(){
        $signer = new Sha256();
        $privateKey = new Key($this->secret);

        $result = $this->decode()->verify($signer, $privateKey);

        return $result;
    }
    /\*\*
 \* 校验参数
 \* @return bool
 \*/
    public function validate(){

        $data = new ValidationData();
        $data->setIssuer($this->iss);
        $data->setAudience($this->aud);

        return $this->decode()->validate($data);
    }

    /\*\*
 \* @return $this
 \*/
    public function encode(){

        $signer = new Sha256();
        $privateKey = new Key($this->secret);
        $time = time(); // 颁发时间

        $this->token = (new Builder())
            ->withHeader('alg', 'HS256')
            ->issuedBy($this->iss)
            ->permittedFor($this->aud)
            ->issuedAt($time)
            ->expiresAt($time + 3600)  // 过期时间
            ->withClaim('uid', $this->uid)  // 自定义参数
            ->getToken($signer, $privateKey);

        return $this;
    }

    /\*\*
 \* 获取token
 \* @return string
 \*/
    public function getToken(){

        return (string)$this->token;

    }

    /\*\*
 \* @return string
 \*/
    public function getUid(){
        return $this->uid;
    }

}

控制器调用

<?php
/\*\*
 \* 老王
 \*
 \*\*/

namespace app\api\controller;
use app\BaseController;
use app\common\lib\auth\JwtAuth;
use app\common\lib\ResponseJson;

class Test extends BaseController
{
    use ResponseJson;
    public function index(){

        // 获取jwtAuth的句柄
        $jwtAuth = JwtAuth::getInstance();
        $token = $jwtAuth->setUid(1)->encode()->getToken();
        
        $this->success(['token' => $token]);
    }
}

3.4 中间件

中间件主要用于拦截或者过滤应用的HTTP请求, 并进行必要的业务处理

  1. 前置中间件: 请求时不会先去执行到控制器的某个方法, 而是先经过中间件, 然后再到某个控制器的某个方法去执行代码,如果中间件有拦截, 流程就会在中间件截断, 不会再往下执行方法, 而且获取不到控制器和方法, 因为会先执行中间件, 再执行控制器的方法
  2. 后置中间件: 访问某个控制器的方法, 会先去执行方法里面的代码内容(不返回输出), 然后执行中间件的代码, 最后才是方法的输出返回, 如果中间件有拦截, 流程就会在中间件内截断, 但是方法内的代码也在前面执行了, 可以获取控制器和方法, 因为会先去执行这个控制器的方法, 再执行中间件

在app/api模块下, 新建middleware文件夹, 然后在该文件夹下创建类

<?php
/\*\*
 \* 老王
 \*
 \*\*/

namespace app\api\middleware;

use app\api\exception\ApiException;
use app\common\lib\auth\JwtAuth;
use app\common\lib\error\ApiErrDesc;
use app\common\lib\ResponseJson;

/\*\*
 \* Class CheckAuth
 \* @package app\api\middleware
 \* 中间件
 \*/
class CheckAuth
{
    /\*\*
 \* @param $request
 \* @param \Closure $next
 \*/
    public function handle($request, \Closure $next){

        $token = $request->header('token');

        if ($token){

            // 校验
            $jwtAuth = JwtAuth::getInstance();
            $jwtAuth->setToken($token);

            if ($jwtAuth->validate() && $jwtAuth->verify()){
                return $next($request);
            }else{
                
                throw new ApiException(ApiErrDesc::ERR\_LOGIN);
            }

        }else{
            throw new ApiException(ApiErrDesc::ERR\_PARAMS);
        }

    }
}

注册中间件
在app/api模块下, 新建middleware.php文件

<?php
// 该模块下的中间件定义文件, 对该模块下的所有控制器都有效, 在middleware下写好中间件后, 需要在该文件下配置绑定
// 如果使得该中间件只针对某一个控制器有效, 可以借助路由来设置, 不需要在该文件下配置绑定, 直接在middleware下写好中间件然后通过路由绑定->middleware()
return [
    app\api\middleware\CheckAuth::class
];

4. 业务逻辑异常处理
4.1 错误码

错误码是用来描述当前接口处理的结果, 是前后端共同的约束
格式:

  1. code 错误码
  2. msg 错误码对应的描述

一般以配置文件( config/status.php )或者类的常量来定义错误码, 统一管理便于维护
在app/common/lib文件夹下新建error, 并在该文件夹下创建类库

<?php
/\*\*
 \* 老王
 \*
 \*\*/

namespace app\common\lib\error;

/\*\*
 \* Class ApiErrDesc
 \* @package app\common\lib\error
 \* APi返回码类库
 \*/
class ApiErrDesc
{
    /\*\*
 \* Api通用错误码
 \* error\_code < 1000
 \*/
    const SUCCESS = [1, 'Success'];
    const UNKNOWN\_ERR = [0, '未知错误'];
    const ERR\_URL = [2, '请求接口不存在'];

    const ERR\_PARAMS = [100, '参数错误'];

    /\*\*
 \* 用户登录相关的错误码
 \* error\_code 1000-1100
 \*/
    const UNKNOWN\_USER = [1001, '用户不存在'];
    const ERR\_PASSWORD = [1002, '密码错误'];
    const ERR\_LOGIN = [1000, '登录过期'];

}

4.2 业务异常

try…catch 可以捕获异常
set_exception_handler set_error_handler设置用户自定义的异常处理函数, 用于没有用try/catch块来捕获的异常
api模块是与客户端交互的接口类库, 出现异常需要按照接口的输出格式返回给客户端, 便于客户端进行操作, TP6中app/ExceptionHandler.php是系统自带的应用异常处理类, 通过页面形式输出错误信息, 但这种并不适用api接口
所以需要在app/api/exception文件夹下新建异常处理的类
自定义接收异常并格式化输出类

<?php
/\*\*
 \* 老王
 \*
 \*\*/

namespace app\api\exception;
use think\exception\Handle;
use think\Response;
use Throwable;
use app\common\lib\ResponseJson;
use app\common\lib\error\ApiErrDesc;
/\*\*
 \* Class ApiHandler
 \* @package app\api\exception
 \* api模块下的异常处理类
 \*/
class ApiHandle extends Handle
{

    protected $httpCode = 500;
    /\*\*
 \* Render an exception into an HTTP response.
 \*
 \* @access public
 \* @param \think\Request $request
 \* @param Throwable $e
 \* @return Response
 \*/
    public function render($request, Throwable $e): Response
    {

        if ($e instanceof ApiException){
            $status = $e->getCode();
            $message = $e->getMessage();
        }else{
			$status = $e->getCode();
			if(!$status || $status < 0){
				$status = ApiErrDesc::UNKNOWN\_ERR[0];
			}
			$message = $e->getMessage() ?: ApiErrDesc::UNKNOWN\_ERR[1];
		}

       
        // 添加自定义异常处理机制
        if (method\_exists($e, 'getStatusCode')){

            $this->httpCode = $e->getStatusCode();
        }

        return ResponseJson::error($status, $message, null, $this->httpCode);
    }

}

自定义抛出异常的类

<?php
/\*\*
 \* 老王
 \*
 \*\*/

namespace app\api\exception;


use think\Exception;


![img](https://img-blog.csdnimg.cn/img_convert/64ec846b6128f31ba0a41098d1490b8f.png)
![img](https://img-blog.csdnimg.cn/img_convert/2375582c78e7fcc695f048a7a18eae23.png)
![img](https://i-blog.csdnimg.cn/blog_migrate/c2b75ec3538a28a6ddae07f4789cfb8c.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**



自定义抛出异常的类

<?php
/\*\*
 \* 老王
 \*
 \*\*/

namespace app\api\exception;


use think\Exception;


[外链图片转存中...(img-dzbmlvwO-1715640208201)]
[外链图片转存中...(img-li6HpIFo-1715640208202)]
[外链图片转存中...(img-rUuESoAK-1715640208202)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[如果你需要这些资料,可以戳这里获取](https://bbs.csdn.net/topics/618658159)**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值