Laravel8使用jwt+redis+mysql 实现登录功能

2020-10-21   阅读:163   分类:后端    标签: Laravel

在现在前后端分离的时代,使用PHP开发APP后台API(接口)是很多公司的选择。但是传统的PHP开发API没有系统的把PHP当做一个工程化的项目来开发,没有明确各个模块的职责,所以本文写的是一种比较通用的PHP开发API的方式,简单的从API输入输出、API鉴权,业务异常处理等模块来描述API各个模块以及各个模块之间的关系。

本文采用laravel8+redis+mysql实现一个简单的登录功能,以及获取用户数据。

一、下载jwt扩展库:使用composer下载

composer require lcobucci/jwt

接着执行,生成自动加载文件

composer dump-autoload

可以参考这篇文章:Laravel8安装jwt扩展 

二、创建数据库和数据表

创建用户表

/*
 Navicat MySQL Data Transfer
 
 Source Server         : localhost_3306
 Source Server Type    : MySQL
 Source Server Version : 50726
 Source Host           : localhost:3306
 Source Schema         : laravel8
 
 Target Server Type    : MySQL
 Target Server Version : 50726
 File Encoding         : 65001
 
 Date: 15/10/2020 14:17:27
*/
 
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
 
-- ----------------------------
-- Table structure for l_user
-- ----------------------------
DROP TABLE IF EXISTS `l_user`;
CREATE TABLE `l_user`  (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,
  `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,
  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL,
  `created_at` timestamp(0) NULL DEFAULT NULL,
  `updated_at` timestamp(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `email`(`email`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;
 
-- ----------------------------
-- Records of l_user
-- ----------------------------
INSERT INTO `l_user` VALUES (1, 'admin', '123456@qq.com', '$2y$10$SojwOG45s8BaDi00NnDvnO4U.Y.BUPsDEwJc5AILAyRrNwoI5b3Wy', NULL, NULL);
 
SET FOREIGN_KEY_CHECKS = 1;

说明:默认账号123456@qq.com  密码:123456

三、创建文件和编写代码

1、   添加路由web.php

<?php
 
use Illuminate\Support\Facades\Route;
Route::get('/info', [App\Http\Controllers\Admin\LoginController::class, 'info'])->name('admin.login.info')->middleware('CheckLogin'); //获取用户信息接口
Route::get('/login', [App\Http\Controllers\Admin\LoginController::class, 'login'])->name('admin.login.login'); //登录接口
?>

2、封装jwt:项目根目录下新建Common\Auth\JwtAuth.php

<?php
namespace App\Http\Common\Auth;
/*
 * 单例 一次请求中所有出现使用jwt的地方都是一个用户
 * class JwtAuth
 *
 * */
 
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\ValidationData;
 
class JwtAuth
{
    /*
     * jwt token
     * */
    private $token;
 
    /*
     * claim iss
     * @var string
     * */
    private $iss = 'api.test.com';
 
    /*
     * claim aud
     * @var string
     * */
    private $aud = 'server_app';
 
    /*
     * claim uid
     * @var
     * */
    private $uid;
 
    /*
    * claim uid
    * @var
    * */
 
    /*
    * claim secrect
    * @var string
    * */
    private $secrect = '@#dslaci%hsbcbbc*hh';
 
    /*
     * decode token
     * @var
     * */
    private $decodeToken;
 
    /*
     * 单例模式 jwtAuth句柄
     * @var
     * */
    private static $instance;
 
    /*
     * 获取jwtAuth的句柄
     * @return JwtAuth
     * */
    public static function getInstace(){
        if(is_null(self::$instance)){
            self::$instance = new self();
        }
        return self::$instance;
    }
    /*
     * 私有化构造函数
     * JwtAuth constructor.
     * */
 
    private function __construct()
    {
    }
    /*
     * 私有化克隆函数
     * */
    private function __clone(){
 
    }
 
    /*
     * 获取token
     * @return string
     * */
    public function getToken(){
        return (string)$this->token;
    }
 
    /*
     * 设置token
     * @param $token
     * @return $this
     * */
    public function setToken($token){
        $this->token = $token;
    }
 
    /*
     *uid
     * @parm $uid
     * */
    public function setUid($uid)
    {
        $this->uid = $uid;
        return $this;
    }
 
    public function getUid()
    {
        return $this->uid;
    }
 
    /*
     * 编码jwt token
     * @return $this
     * */
    public function encode()
    {
        $time = time();
        $this->token = (new Builder())->setHeader('alg','HS256')
            ->setIssuer('api.test.com')
            ->setAudience($this->aud)
            ->setIssuedAt($time)
            ->setExpiration($time + 3600)
            ->set('uid', $this->uid)
            ->sign(new Sha256(),$this->secrect)
            ->getToken();
        return $this;
    }
    /*
     * parse string token
     * @return \Lcobucci\JWT\Token
     * */
    public function decode()
    {
        if(!$this->decodeToken){
            $this->decodeToken = (new Parser())->parse((string)$this->token);
            $this->uid = $this->decodeToken->getClaim('uid');
        }
        return $this->decodeToken;
    }
 
    /*
     * verify token
     * 验证token有没被篡改
     * */
    public function verify()
    {
        $result = $this->decode()->verify(new Sha256(),$this->secrect);
        return $result;
    }
    /*
     * validate
     * @return bool
     * */
    public function validate()
    {
        $data = new ValidationData();
        $data->setIssuer($this->iss);
        $data->setAudience($this->aud);
        return $this->decode()->validate($data);
    }
}
?>

3、   创建中间件:app\Http\Middleware\CheckLogin.php

<?php
namespace App\Http\Middleware;
 
use App\Http\Common\Auth\JwtAuth;
use Closure;
use Illuminate\Http\Request;
 
class CheckLogin
{
    use ResponseJson;
 
    /**
     * Handle an incoming request.
     *
     * @param \Illuminate\Http\Request $request
     * @param \Closure $next
     * @return mixed
     */
    public function handle(Request $request, Closure $next)
    {
        $token = $request->input('token');
        if ($token) {
            $jwtAuth = JwtAuth::getInstace();
            $jwtAuth->setToken($token);
 
            if ($jwtAuth->validate() && $jwtAuth->verify()) {
                return $next($request);
            } else {
                return response()->json(['code'=>500,'msg'=>'登录过期']);
            }
        } else {
            return response()->json(['code'=>500,'msg'=>'参数错误']);
        }
 
    }
}
?>

4、   登录接口和获取数据接口,使用redis缓存加速用户信息接口获取数据。

<?php
 
namespace App\Http\Controllers\Admin;
 
use App\Http\Common\Auth\JwtAuth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
 
class LoginController extends Controller
{
    /*
     * 用户登录
     *
     * @param Request $request
     * @return false|string
     * */
    public function login(Request $request){
        //获取客户端传递的参数
        $email = $request->input('email');
        $password = $request->input('password');
 
        //去数据库中查询改用户信息
        $res=DB::table('user')->where('email',$email)->first();
        if(!$res){
            return response()->json(['code'=>500,'msg'=>'用户不存在']);
        }
        //password_hash()
        $userPasswordHash = $res->password;
        if(!password_verify($password,$userPasswordHash)){
           return response()->json(['code'=>500,'msg'=>'用户密码错误']);
 
        }
        $jwtAuth = JwtAuth::getInstace();
        $token = $jwtAuth->setUid($res->id)->encode()->getToken();
return response()->json([
'code'=>200,'msg'=>'登录成功', 'token'=>$token
]);
}
/*
     * 用户信息获取
     *
     * @return false|string
     * */
 
    public function info(){
        $jwtAuth = JwtAuth::getInstace();
        $uid = $jwtAuth->getUid();
        $cacheUserInfo = Redis::get('uid:'. $uid);
//        dd($cacheUserInfo);
        if(!$cacheUserInfo){
            $user = DB::table('user')->where('id',$uid)->first();
            if(!$user){
return response()->json([
'code'=>500,'msg'=>'用户密码错误'
]);
            }
            Redis::setex('uid:'.$uid,3600,json_encode($user) );
        }else{
            $user = json_decode($cacheUserInfo);
        }
return response()->json([
'code'=>500,
'msg'=>'获取成功',
'name'=>$user->name,
'email'=>$user->email
]);
    }
}
?>

四、测试接口数据[使用postman来测试接口数据]

1、访问登录接口:携带email和password

http://www.laravel8.com/login?email=123456@qq.com&password=123456

image.png

2、访问获取数据接口:携带上面生成的token,返回用户信息

http://www.laravel8.com/info?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhcGkudGVzdC5jb20iLCJhdWQiOiJzZXJ2ZXJfYXBwIiwiaWF0IjoxNjAyNzQxMDYyLCJleHAiOjE2MDI3NDQ2NjIsInVpZCI6MX0.UdQP30IhNuhe-1jd_iYXHIl6-23EwNisea4oSe_0z7c

image.png

以上是一个简单的使用jwt实现登录登录功能,供大家参看。


【腾讯云】11.11 云上盛惠,云产品限时抢购,1核2G云服务器首年88元

‘简忆博客’微信公众号 扫码关注‘简忆博客’微信公众号,获取最新文章动态
转载:请说明文章出处“来源简忆博客”。http://www.tpxhm.com/adetail/476.html

×
觉得文章有用就打赏一下文章作者
微信扫一扫打赏 微信扫一扫打赏
支付宝扫一扫打赏 支付宝扫一扫打赏

文章评论(0)

登录
简忆博客壁纸 头像

简忆博客
仕而优则学,学而优则仕。

置顶推荐

打赏本站

如果你觉得本站很棒,可以通过扫码支付打赏哦!
微信扫码:你说多少就多少~
微信扫码
支付宝扫码:你说多少就多少~
支付宝扫码
×