在现在前后端分离的时代,使用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

2、访问获取数据接口:携带上面生成的token,返回用户信息
http://www.laravel8.com/info?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhcGkudGVzdC5jb20iLCJhdWQiOiJzZXJ2ZXJfYXBwIiwiaWF0IjoxNjAyNzQxMDYyLCJleHAiOjE2MDI3NDQ2NjIsInVpZCI6MX0.UdQP30IhNuhe-1jd_iYXHIl6-23EwNisea4oSe_0z7c

以上是一个简单的使用jwt实现登录登录功能,供大家参看。
关于简忆
简忆诞生的故事



粤ICP备16092285号
文章评论(0)