梳理逻辑

1,public /index.php 入口文件

 

 

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------

// [ 应用入口文件 ]

//处理跨域Options预检请求
if($_SERVER['REQUEST_METHOD'] == 'OPTIONS'){
    //允许的源域名
    header("Access-Control-Allow-Origin: *");
    //允许的请求头信息
    header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization");
    //允许的请求类型
    header('Access-Control-Allow-Methods: GET, POST, PUT,DELETE,OPTIONS,PATCH');
    exit;
}

// 定义应用目录
define('APP_PATH', __DIR__ . '/../application/');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';

解决跨域问题

使用了路由,说白了就是将 url 和 module/controller/action 对应起来!

 

 

我们要继续梳理, token的工具类:

里面核心代码就是生成token ,还有一个通过token 获取userId 的操作

用到的类库,放入到这个模块中了,vendor 扩展目录模块,验证码类,分页的扩展模块都放这里! 通过composer 安装

 

 

<?php
namespace tools\jwt;

use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\ValidationData;

/**
 * Created by PhpStorm.
 * User: asus
 * Date: 2019/4/5
 * Time: 13:02
 */
class Token
{
    // config
    private static $_config = array(
        'audience' => 'http://www.16zy8.com',
        'id' => '3f2g57a92aa',
        'sign' => 'pinyougou',
        'issuer' => 'http://www.16faka.xyz',
        'expire' => 3600*24
    );

    //生成token
    public static function getToken($user_id){

        //签名对象
        $signer = new Sha256();
        //获取当前时间戳
        $time = time();
        //设置签发人、接收人、唯一标识、签发时间、立即生效、过期时间、用户id、签名
        $token = (new Builder())->issuedBy(self::$_config['issuer'])
            ->canOnlyBeUsedBy(self::$_config['audience'])
            ->identifiedBy(self::$_config['id'], true)
            ->issuedAt($time)
            ->canOnlyBeUsedAfter($time-1)
            ->expiresAt($time + self::$_config['expire'])
            ->with('user_id', $user_id)
            ->sign($signer, self::$_config['sign'])
            ->getToken();
        return (string)$token;
    }

    //从请求信息中获取token令牌
    public static function getRequestToken()
    {
        if (empty($_SERVER['HTTP_AUTHORIZATION'])) {
            return false;
        }

        $header = $_SERVER['HTTP_AUTHORIZATION'];
        $method = 'bearer';
        //去除token中可能存在的bearer标识
        return trim(str_ireplace($method, '', $header));
    }

    //从token中获取用户id (包含token的校验)
    // 只要token不正确或者过期都会返回Null, 通过正确返回userID
    public static function getUserId($token = null)
    {
        $user_id = null;

        // 从bearer 中取出token,若有的话,则放行
        $token = empty($token)?self::getRequestToken():$token;

        // 有token,则执行该方法
        if (!empty($token)) {
            //为了注销token 加以下if判断代码
            $delete_token = cache('delete_token') ?: [];
            if(in_array($token, $delete_token)){
                //token已被删除(注销)
                return $user_id;
            }
            $token = (new Parser())->parse((string) $token);
            //验证token
            $data = new ValidationData();
            $data->setIssuer(self::$_config['issuer']);//验证的签发人
            $data->setAudience(self::$_config['audience']);//验证的接收人
            $data->setId(self::$_config['id']);//验证token标识

            if (!$token->validate($data)) {
                //token验证失败
                return $user_id;
            }

            //验证签名
            $signer = new Sha256();
            if (!$token->verify($signer, self::$_config['sign'])) {
                //签名验证失败
                return $user_id;
            }
            //从token中获取用户id
            $user_id = $token->getClaim('user_id');
        }

        return $user_id;
    }
}

有了 验证码类,具体使用:

 

访问下看看

代码没有问题,

我们看下baseapi

<?php

namespace app\adminapi\controller;

use think\Controller;

class BaseApi extends Controller
{
    //不需要验证token 的列表
    protected $no_login = ['login/captcha', 'login/login','index/index'];
    //控制器的初始化方法(和 直接写构造方法 二选一)
    protected function _initialize()
    {
        //实现父类的初始化方法,空方法
        parent::_initialize();

        //初始化代码
        //处理跨域请求
        //允许的源域名
        header("Access-Control-Allow-Origin: *");
        //允许的请求头信息
        header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization");
        //允许的请求类型
        header('Access-Control-Allow-Methods: GET, POST, PUT,DELETE,OPTIONS,PATCH');

        try{
            //登录检测
            //获取当前请求的控制器方法名称
            $path = strtolower($this->request->controller()) . '/' . $this->request->action();
            if(!in_array($path, $this->no_login)){
                //需要做登录检测
                $user_id = \tools\jwt\Token::getUserId();
                if(empty($user_id)){
                    $this->fail('token验证失败', 403);
                }
                //将得到的用户id 放到请求信息中去  方便后续使用
                $this->request->get('user_id', $user_id);
                $this->request->post('user_id', $user_id);
            }
        }catch (\Exception $e){
            //token解析失败
            $this->fail('token解析失败', 404);
        }

    }

    /**
     * 通用的响应
     * @param int $code 错误码
     * @param string $msg 错误信息
     * @param array $data 返回数据
     */
    protected function response($code=200, $msg='success', $data=[])
    {
        $res = [
            'code' => $code,
            'msg' => $msg,
            'data' => $data
        ];
        //原生php写法
        echo json_encode($res, JSON_UNESCAPED_UNICODE);die;
        //框架写法
        //json($res)->send();

    }
    /**
     * 成功的响应
     * @param array $data 返回数据
     * @param int $code 错误码
     * @param string $msg 错误信息
     */
    protected function ok($data=[], $code=200, $msg='success')
    {
        $this->response($code, $msg, $data);
    }

    /**
     * 失败的响应
     * @param $msg 错误信息
     * @param int $code 错误码
     * @param array $data 返回数据
     */
    protected function fail($msg, $code=500, $data=[])
    {
        $this->response($code, $msg, $data);
    }
}

 

在上面中, 我把index/index 放入了不需要验证token 的列表,所以不需要验证token 

直接进入了 index方法,所以才打印出来了,当然喽,我们是为了测试用的!

若我们将index/index从 不需要验证token 的列表 移除,则会继续验证token 的逻辑

类似的思路,vue 的路由控制, beforeEach 方法中,为每个路由添加meta 属性作为标记

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值