Browse Source

优化登录注册接口,用户信息接口,jwt优化

master
wanghongjun 1 year ago
parent
commit
3f060720ef
  1. 2
      app/admin/controller/user/Admin.php
  2. 3
      app/admin/model/User.php
  3. 6
      app/admin/view/user/admin/add.html
  4. 6
      app/admin/view/user/admin/edit.html
  5. 4
      app/api/controller/ApiController.php
  6. 58
      app/api/controller/Index.php
  7. 91
      app/api/controller/Passport.php
  8. 32
      app/api/controller/User.php
  9. 5
      app/api/middleware.php
  10. 40
      app/api/middleware/CsrfMiddleware.php
  11. 36
      app/api/middleware/JWTAuth.php
  12. 29
      app/api/middleware/LcJWTAuth.php
  13. 147
      app/api/service/JWTService.php
  14. 128
      app/api/service/LcJWTService.php
  15. 110
      app/api/service/UserService.php
  16. 4
      composer.json

2
app/admin/controller/user/Admin.php

@ -76,6 +76,7 @@ class Admin extends AdminController
} }
$save ? $this->success('保存成功') : $this->error('保存失败'); $save ? $this->success('保存成功') : $this->error('保存失败');
} }
$this->assign('genderArr', $this->model->genderArr);
return $this->fetch(); return $this->fetch();
} }
@ -103,6 +104,7 @@ class Admin extends AdminController
$save ? $this->success('保存成功') : $this->error('保存失败'); $save ? $this->success('保存成功') : $this->error('保存失败');
} }
$this->assign('row', $row); $this->assign('row', $row);
$this->assign('genderArr', $this->model->genderArr);
return $this->fetch(); return $this->fetch();
} }

3
app/admin/model/User.php

@ -11,4 +11,7 @@ class User extends TimeModel
protected $defaultSoftDelete = '0'; protected $defaultSoftDelete = '0';
public $genderArr = [
1 => '男', 2 => '女', 3 => '未知'
];
} }

6
app/admin/view/user/admin/add.html

@ -47,9 +47,9 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label required">性别</label> <label class="layui-form-label required">性别</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="radio" name="gender" value="1" title="男" checked> {foreach $genderArr as $gender => $title}
<input type="radio" name="gender" value="2" title="女"> <input type="radio" name="gender" value="{$gender}" title="{$title}" {if $gender == 1}checked{/if}>
<input type="radio" name="gender" value="3" title="未知"> {/foreach}
</div> </div>
</div> </div>

6
app/admin/view/user/admin/edit.html

@ -23,9 +23,9 @@
<div class="layui-form-item"> <div class="layui-form-item">
<label class="layui-form-label required">性别</label> <label class="layui-form-label required">性别</label>
<div class="layui-input-block"> <div class="layui-input-block">
<input type="radio" name="gender" value="1" title="男" {if $row.gender == 1}checked{/if}> {foreach $genderArr as $gender => $title}
<input type="radio" name="gender" value="2" title="女" {if $row.gender == 2}checked{/if}> <input type="radio" name="gender" value="{$gender}" title="{$title}" {if $row.gender == $gender}checked{/if}>
<input type="radio" name="gender" value="3" title="未知" {if $row.gender == 3}checked{/if}> {/foreach}
</div> </div>
</div> </div>

4
app/api/controller/ApiController.php

@ -1,6 +1,7 @@
<?php <?php
namespace app\api\controller; namespace app\api\controller;
use app\api\middleware\LcJWTAuth;
use think\App; use think\App;
use think\response\Json; use think\response\Json;
use think\route\dispatch\Controller; use think\route\dispatch\Controller;
@ -12,6 +13,9 @@ use think\Request;
* @package app\api\controller * @package app\api\controller
*/ */
abstract class ApiController { abstract class ApiController {
protected $middleware = [LcJWTAuth::class];
/** /**
* Request实例 * Request实例
* @var Request * @var Request

58
app/api/controller/Index.php

@ -2,17 +2,24 @@
namespace app\api\controller; namespace app\api\controller;
use app\BaseController;
use app\Request; use app\Request;
// for jwt // for JWT
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Builder; use Lcobucci\JWT\Builder;
// use Lcobucci\JWT\Signer\Hmac\Sha256;
// use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Token;
// use DateTimeImmutable;
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256; use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory; use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Token; use DateTimeImmutable;
use Lcobucci\JWT\Token\Plain;
use Lcobucci\JWT\Validation\RequiredConstraintsViolated;
use Lcobucci\JWT\Validation\Constraint\SignedWith;
class Index extends BaseController class Index extends ApiController
{ {
// //
public function index(Request $request) public function index(Request $request)
@ -24,7 +31,8 @@ class Index extends BaseController
$data = $request->post(); $data = $request->post();
// 用户密码 // 用户密码
$salt = isset($data['salt'])?$data['salt']:makeSalt(6); $salt = isset($data['salt'])?$data['salt']:makeSalt(6);
$arr['encpass']=password($data['upass']);
$arr['encpass']=password($data['upass'].$salt);
$arr['salt']=$salt; $arr['salt']=$salt;
} else { } else {
$arr = ["ver" => "00", "date" => time()]; $arr = ["ver" => "00", "date" => time()];
@ -59,30 +67,50 @@ class Index extends BaseController
// //
$config = Configuration::forSymmetricSigner($signer,$key); $config = Configuration::forSymmetricSigner($signer,$key);
//$builder = new Builder();
// 设置发行时间和过期时间
$now = new DateTimeImmutable(); // 当前时间 $now = new DateTimeImmutable(); // 当前时间
// 设置发行时间和过期时间
$secondsToAdd = (int) config('jwt.token_ttl');
$expiresAt = $now->add(new \DateInterval('PT' . $secondsToAdd . 'S'));
// $token = $builder
// ->issuedAt($now) // iat: 发行时间
// ->expiresAt($expiresAt) // exp: 过期时间
// ->withIssuer('iss', 'xtt') // iss: 发行人
// ->withSubject('sub', 'xtoken') // sub: 主题
// ->withAudience('aud', 'ttc'); // aud: 受众
$token = $config->builder() $token = $config->builder()
// 签发人 // 签发人
->issuedBy('https://douyin.xingtongworld.com/') ->issuedBy('https://douyin.xingtongworld.com/')
// 受众 // 受众
->permittedFor('https://douyin.xingtongworld.com/') ->permittedFor('https://douyin.xingtongworld.com/')
// JWT ID 编号 唯一标识 // JWT ID 编号 唯一标识
->identifiedBy($claims['id']) ->identifiedBy($claims['id'])
// 签发时间 // 签发时间
->issuedAt($now) ->issuedAt($now)
// 在1分钟后才可使用 // 在1分钟后才可使用
// ->canOnlyBeUsedAfter($now->modify('+1 minute')) // ->canOnlyBeUsedAfter($now->modify('+1 minute'))
// 过期时间1小时 // 过期时间1小时
->expiresAt($now->modify('+1 hour')) ->expiresAt($now->modify('+1 hour'))
// 自定义uid 额外参数 // 自定义uid 额外参数
->withClaim('uid', $claims['id']) ->withClaim('uid', $claims['id'])
->withClaim('name',$claims['nick_name']) ->withClaim('name',$claims['nick_name'])
// 自定义header 参数 // 自定义header 参数
// ->withHeader('foo', 'bar') // ->withHeader('foo', 'bar')
// 生成token // 生成token
->getToken($config->signer(), $config->signingKey()); ->getToken($config->signer(), $config->signingKey());
// base64 // base64
return $token->toString(); return $token->toString();
// foreach ($claims as $key => $value) {
// $token = $token->withClaim($key, $value);
// }
// return (string) $token->sign($signer, $key);
} }
} }

91
app/api/controller/Passport.php

@ -1,90 +1,79 @@
<?php <?php
namespace app\api\controller; namespace app\api\controller;
use app\api\middleware\LcJWTAuth;
use app\api\service\LcJWTService;
use app\api\service\UserService; use app\api\service\UserService;
use think\Controller; use think\Controller;
use think\exception\ValidateException;
use think\response\Json; use think\response\Json;
/** /**
* 用户账户控制器 * 用户账户控制器
* 功能:MVC 中的C,处理用户输入和反馈给用户 * 功能:MVC 中的C,处理用户输入和反馈给用户
*/ */
class Passport extends ApiController{ class Passport extends ApiController
{
protected $middleware
= [
LcJWTAuth::class => [
'except' => ['login', 'register']
]
];
/** /**
* 登录 * 登录
*/ */
public function login():Json public function login(): Json
{ {
if (!$this->request->isPost()) { if (!$this->request->isPost()) {
return $this->renderError('不支持GET请求'); return $this->renderError('不支持GET请求');
} }
$data = $this->postData(); $data = $this->postData();
try {
validate()->rule([
'uname|用户名' => 'require',
'upass|密码' => 'require',
])->check($data);
} catch (ValidateException $v) {
return $this->renderError($v->getMessage());
}
$model = new UserService; $model = new UserService;
// if (($userInfo = $model->login($data['uname'], $data['upass'])) === false) {
$data = $this->postData();
if (($userInfo = $model->login($data['uname'],$data['upass'])) === false) {
return $this->renderError($model->getError() ?: '登录失败'); return $this->renderError($model->getError() ?: '登录失败');
} }
return $this->renderSuccess([ return $this->renderSuccess([
'userId' => $userInfo['uid'], 'userId' => $userInfo['uid'],
'token' => $model->getToken($userInfo['uid'],$userInfo['nick_name']) 'token' => LcJWTService::createToken($userInfo['uid'], $data['uname'])
], ''); ], '登录成功');
} }
/** /**
* 用户注册 * 用户注册
* @return Json * @return Json
*/ */
public function register():Json public function register(): Json
{ {
if (!$this->request->isPost()) { if (!$this->request->isPost()) {
return $this->renderError('不支持GET请求'); return $this->renderError('不支持GET请求');
} }
$post = $this->postData();
try {
validate()->rule([
'uname|用户名' => 'require',
'upass|密码' => 'require',
'qr_upass|确认密码' => 'require|confirm:upass',
'phone|手机号' => 'require|mobile'
])->check($post);
} catch (ValidateException $v) {
return $this->renderError($v->getMessage());
}
$model = new UserService; $model = new UserService;
if (($userInfo = $model->register($this->postData())) === false) { if (($userInfo = $model->register($post)) === false) {
return $this->renderError($model->getError() ?: '注册失败'); return $this->renderError($model->getError() ?: '注册失败');
} }
return $this->renderSuccess("注册成功"); return $this->renderSuccess("注册成功");
} }
}
}
// app/controller/Index.php
// namespace app\controller;
// use app\service\JWTService;
// use think\Request;
// class IndexController
// {
// protected $jwtService;
// public function __construct(JWTService $jwtService)
// {
// $this->jwtService = $jwtService;
// }
// public function login(Request $request)
// {
// $username = $request->param('username');
// $password = $request->param('password');
// // 假设验证用户名和密码成功
// $claims = ['id' => 1, 'username' => $username];
// $token = $this->jwtService->createToken($claims);
// return json(['token' => $token]);
// }
// public function protectedRoute(Request $request)
// {
// $claims = $request->attributes->get('claims');
// if (empty($claims)) {
// return json(['error' => 'Unauthorized'], 401);
// }
// return json(['message' => 'Welcome, ' . $claims['username']]);
// }
// }

32
app/api/controller/User.php

@ -0,0 +1,32 @@
<?php
namespace app\api\controller;
use app\admin\model\User as UserModel;
use app\api\middleware\LcJWTAuth;
use think\response\Json;
class User extends ApiController
{
public function getUserData():Json
{
if (!$this->request->isPost()) {
return $this->renderError('不支持GET请求');
}
$data = $this->postData();
$model = new UserModel();
$field = 'password,salt,last_login_time,create_time,update_time,delete_time';
$row = $model->where('uid', $data['uid'])->withoutField($field)->find();
if ($row->isEmpty()) {
return $this->renderError($model->getError() ?: '用户不存在');
}
if ($row['status'] != 1) return $this->renderError('用户被禁用');
unset($row['status']);
if ($row['gender']) {
$row['gender'] = $model->genderArr[$row['gender']] ?? '';
}
return $this->renderSuccess($row->toArray());
}
}

5
app/api/middleware.php

@ -8,9 +8,4 @@ return [
// 系统操作日志 // 系统操作日志
// \app\admin\middleware\SystemLog::class, // \app\admin\middleware\SystemLog::class,
// Csrf安全校验
// \app\api\middleware\CsrfMiddleware::class,
// jwt 中间件
\app\api\middleware\JWTAuth::class,
]; ];

40
app/api/middleware/CsrfMiddleware.php

@ -1,40 +0,0 @@
<?php
namespace app\api\middleware;
use app\Request;
use CsrfVerify\drive\ThinkphpCache;
use CsrfVerify\entity\CsrfVerifyEntity;
use CsrfVerify\interfaces\CsrfVerifyInterface;
use think\facade\Session;
class CsrfMiddleware
{
use \app\common\traits\JumpTrait;
public function handle(Request $request, \Closure $next)
{
if (env('EASYADMIN.IS_CSRF', true)) {
if (!in_array($request->method(), ['GET', 'HEAD', 'OPTIONS'])) {
// 跨域校验
$refererUrl = $request->header('REFERER', null);
$refererInfo = parse_url($refererUrl);
$host = $request->host(true);
if (!isset($refererInfo['host']) || $refererInfo['host'] != $host) {
$this->error('当前请求不合法!');
}
// CSRF校验
$ckCsrfToken = $request->post('ckCsrfToken', null);
$data = !empty($ckCsrfToken) ? ['__token__' => $ckCsrfToken] : [];
$check = $request->checkToken('__token__', $data);
if (!$check) {
$this->error('请求验证失败,请重新刷新页面!');
}
}
}
return $next($request);
}
}

36
app/api/middleware/JWTAuth.php

@ -1,36 +0,0 @@
<?php
namespace app\api\middleware;
use app\api\service\JWTService;
use think\Exception;
use think\Request;
class JWTAuth
{
protected $jwtService;
public function __construct(JWTService $jwtService)
{
$this->jwtService = $jwtService;
}
public function handle(Request $request, \Closure $next)
{
$token = $request->header('Authorization');
if (!$token) {
throw new Exception('Missing token');
}
$claims = $this->jwtService->verifyToken($token);
if (empty($claims)) {
throw new Exception('Invalid token');
}
// 将 claims 存储到 request 对象中
$request->attributes->set('claims', $claims);
return $next($request);
}
}

29
app/api/middleware/LcJWTAuth.php

@ -0,0 +1,29 @@
<?php
namespace app\api\middleware;
use app\api\service\LcJWTService;
use app\Request;
class LcJWTAuth
{
public function handle(Request $request, \Closure $next)
{
$token = $request->header('token');
if (!$token) {
return json(['code' => 401, 'msg' => 'token cannot be empty']);
}
$data = LcJWTService::parseToken($token);
$claims = $data['claims'];
$validateRes = LcJWTService::validationToken($token, $claims->get('uid'));
if ($validateRes !== true) {
return json(['code' => 401, 'msg' => 'token verification failed']);
}
return $next($request);
}
}

147
app/api/service/JWTService.php

@ -1,147 +0,0 @@
<?php
namespace app\api\service;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Token;
use DateTimeImmutable;
class JWTService
{
private $secret;
public function __construct()
{
$this->secret = config('jwt.secret');
}
public function createToken(array $claims): string
{
$signer = new Sha256();
$key = InMemory::plainText($this->secret);
$now = new DateTimeImmutable(); // 当前时间
$builder = new Builder();
// 设置发行时间和过期时间
$secondsToAdd = (int) config('jwt.token_ttl');
$expiresAt = $now->add(new \DateInterval('PT' . $secondsToAdd . 'S'));
$token = $builder
->issuedAt($now) // iat: 发行时间
->expiresAt($expiresAt) // exp: 过期时间
// 使用专用方法设置注册声明
->withIssuer('your_issuer') // iss: 发行人
->withSubject('your_subject') // sub: 主题
->withAudience('your_audience'); // aud: 受众
// 添加自定义 Claims
foreach ($claims as $key => $value) {
$token = $token->withClaim($key, $value); // 自定义声明仍然可以使用 withClaim
}
// 构建并签名 Token
$signedToken = $token->sign($signer, $key);
return (string) $signedToken;
}
public function verifyToken(string $token): array
{
try {
$parser = new \Lcobucci\JWT\Parser();
$token = $parser->parse($token);
if ($token->verify(new Sha256(), InMemory::plainText($this->secret))) {
return $token->getClaims();
}
} catch (\Exception $e) {
// 处理异常
}
return [];
}
}
// app/service/JWTService.php
namespace app\service;
use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
use Lcobucci\JWT\Token;
use DateTimeImmutable;
class JWTService
{
private $secret;
public function __construct()
{
$this->secret = config('jwt.secret');
}
public function createToken(array $claims): string
{
$signer = new Sha256();
$key = InMemory::plainText($this->secret);
$now = new DateTimeImmutable(); // 当前时间
$builder = new Builder();
// 设置发行时间和过期时间
$secondsToAdd = (int) config('jwt.token_ttl');
$expiresAt = $now->add(new \DateInterval('PT' . $secondsToAdd . 'S'));
$token = $builder
->issuedAt($now) // iat: 发行时间
->expiresAt($expiresAt) // exp: 过期时间
// 使用辅助方法设置注册声明
->withRegisteredClaim('iss', 'your_issuer') // iss: 发行人
->withRegisteredClaim('sub', 'your_subject') // sub: 主题
->withRegisteredClaim('aud', 'your_audience'); // aud: 受众
// 添加自定义 Claims
foreach ($claims as $key => $value) {
$token = $token->withClaim($key, $value); // 自定义声明仍然可以使用 withClaim
}
// 构建并签名 Token
$signedToken = $token->sign($signer, $key);
return (string) $signedToken;
}
public function verifyToken(string $token): array
{
try {
$parser = new \Lcobucci\JWT\Parser();
$token = $parser->parse($token);
if ($token->verify(new Sha256(), InMemory::plainText($this->secret))) {
return $token->getClaims();
}
} catch (\Exception $e) {
// 处理异常
}
return [];
}
/**
* 辅助方法用于设置注册声明。
*
* @param string $claimName
* @param mixed $claimValue
* @return \Lcobucci\JWT\Builder
*/
private function withRegisteredClaim(string $claimName, $claimValue): Builder
{
return (new Builder())->withClaim($claimName, $claimValue);
}
}

128
app/api/service/LcJWTService.php

@ -0,0 +1,128 @@
<?php
namespace app\api\service;
use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
use DateTimeImmutable;
use Lcobucci\JWT\Token\Plain;
use Lcobucci\JWT\Validation\RequiredConstraintsViolated;
use Lcobucci\JWT\Validation\Constraint\SignedWith;
class LcJWTService
{
protected static $url = 'https://douyin.xingtongworld.com/';
/**
* 配置秘钥加密
* @return Configuration
*/
public static function getConfig()
{
$configuration = Configuration::forSymmetricSigner(
// You may use any HMAC variations (256, 384, and 512)
new Sha256(),
// replace the value below with a key of your own!
InMemory::base64Encoded(config('jwt.secret'))
// You may also override the JOSE encoder/decoder if needed by providing extra arguments here
);
return $configuration;
}
/**
* 签发令牌
*/
public static function createToken(int $userId,string $uname)
{
$config = self::getConfig();
assert($config instanceof Configuration);
$now = new DateTimeImmutable();
$token = $config->builder()
// 签发人
->issuedBy(self::$url)
// 受众
->permittedFor(self::$url)
// JWT ID 编号 唯一标识
->identifiedBy($userId)
// 签发时间
->issuedAt($now)
// 在1分钟后才可使用
// ->canOnlyBeUsedAfter($now->modify('+1 minute'))
// 过期时间1小时
->expiresAt($now->modify('+1 hour'))
// 自定义uid 额外参数
->withClaim('uid', $userId)
->withClaim('name', $uname)
// 自定义header 参数
->withHeader('foo', 'bar')
// 生成token
->getToken($config->signer(), $config->signingKey());
return $token->toString();
}
/**
* 解析令牌
*/
public static function parseToken(string $token)
{
$config = self::getConfig();
assert($config instanceof Configuration);
$token = $config->parser()->parse($token);
assert($token instanceof Plain);
return [
'header' => $token->headers(),// Retrieves the token headers
'claims' => $token->claims()// Retrieves the token claims
];
}
/**
* 验证令牌
*/
public static function validationToken(string $token, int $userId)
{
$config = self::getConfig();
assert($config instanceof Configuration);
$token = $config->parser()->parse($token);
assert($token instanceof Plain);
//Lcobucci\JWT\Validation\Constraint\IdentifiedBy: 验证jwt id是否匹配
//Lcobucci\JWT\Validation\Constraint\IssuedBy: 验证签发人参数是否匹配
//Lcobucci\JWT\Validation\Constraint\PermittedFor: 验证受众人参数是否匹配
//Lcobucci\JWT\Validation\Constraint\RelatedTo: 验证自定义cliam参数是否匹配
//Lcobucci\JWT\Validation\Constraint\SignedWith: 验证令牌是否已使用预期的签名者和密钥签名
//Lcobucci\JWT\Validation\Constraint\ValidAt: 验证要求iat,nbf和exp(支持余地配置)
//验证jwt id是否匹配
$validate_jwt_id = new \Lcobucci\JWT\Validation\Constraint\IdentifiedBy($userId);
$config->setValidationConstraints($validate_jwt_id);
//验证签发人url是否正确
$validate_issued = new \Lcobucci\JWT\Validation\Constraint\IssuedBy(self::$url);
$config->setValidationConstraints($validate_issued);
//验证客户端url是否匹配
$validate_aud = new \Lcobucci\JWT\Validation\Constraint\PermittedFor(self::$url);
$config->setValidationConstraints($validate_aud);
//验证是否过期
$timezone = new \DateTimeZone('Asia/Shanghai');
$now = new \Lcobucci\Clock\SystemClock($timezone);
$validate_jwt_at = new \Lcobucci\JWT\Validation\Constraint\ValidAt($now);
$config->setValidationConstraints($validate_jwt_at);
$constraints = $config->validationConstraints();
try {
$config->validator()->assert($token, ...$constraints);
return true;
} catch (RequiredConstraintsViolated $e) {
// list of constraints violation exceptions:
return $e->getMessage();
}
}
}

110
app/api/service/UserService.php

@ -1,7 +1,11 @@
<?php <?php
declare (strict_types=1); declare (strict_types=1);
namespace app\api\service; namespace app\api\service;
use app\api\model\User;
// for JWT
use Lcobucci\JWT\Configuration; use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256; use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory; use Lcobucci\JWT\Signer\Key\InMemory;
@ -9,30 +13,36 @@ use DateTimeImmutable;
use Lcobucci\JWT\Token\Plain; use Lcobucci\JWT\Token\Plain;
use Lcobucci\JWT\Validation\RequiredConstraintsViolated; use Lcobucci\JWT\Validation\RequiredConstraintsViolated;
use Lcobucci\JWT\Validation\Constraint\SignedWith; use Lcobucci\JWT\Validation\Constraint\SignedWith;
/** /**
* 用户表 * 用户表
*/ */
class UserService { class UserService
public function mktoken(){ {
// jwt
$guid = get_guid_v4();
$dtime = time();
return md5(uniqid($guid.$dtime,true));
}
/** /**
* 用户登录操作,传入用户查询后才对比密码 * 用户登录操作,传入用户查询后才对比密码
* @param string $uname
* @param string $pass
* @return User|array|false|int|mixed|\think\Model
* @throws \cores\exception\BaseException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/ */
public function login(string $uname,string $pass){ public function login(string $uname, string $pass)
{
// query db // query db
$drs = User::where(['nick_name'=>$uname,'delete_time'=>0])->find(); $drs = User::where(['nick_name' => $uname, 'delete_time' => 0])->find();
// 异常处理 // 异常处理
if(!isset($drs)){ if (!isset($drs)) {
throwError('用户不存在'); throwError('用户不存在');
return -1; return -1;
}else{ } else {
$fpass = password($pass.$drs['salt']); $fpass = password($pass . $drs['salt']);
// var_dump($fpass.'|'.$drs['password']);
// exit;
// 对比密码 // 对比密码
if($drs['password'] != $fpass){ if ($drs['password'] != $fpass) {
throwError('密码错误'); throwError('密码错误');
return false; return false;
} }
@ -43,75 +53,27 @@ class UserService {
} }
/** /**
* @param array $arr * @param array $data
* @return bool * @return bool
*/ */
public function register(array $arr){ public function register(array $data): bool
{
$arr = [
'nick_name' => $data['uname'],
'password' => $data['upass'],
'mobile' => $data['phone'],
];
$salt = makeSalt(6); $salt = makeSalt(6);
// 密码加密 // 密码加密
$arr['password'] = password($arr['password'].$salt); $arr['password'] = password($arr['password'] . $salt);
// 生成salt // 生成salt
$arr['salt'] = $salt; $arr['salt'] = $salt;
$dtime =time(); $dtime = time();
$arr['create_time'] = $dtime; $arr['create_time'] = $dtime;
$arr['update_time'] = $dtime; $arr['update_time'] = $dtime;
// 保存 // 保存
$model = new User; $model = new User;
$uid = $model->save($arr); $uid = $model->save($arr);
return isset($uid)?true:false; return (bool)$uid;
}
/**
* 根据uid,nick_name 换取JWT
* @param int $userId
* @param string $uname
* @return string
* @throws \Exception
*/
public function getToken(int $userId,string $uname): string
{
static $token = '';
if (empty($token)) {
$token = $this->makeToken($userId,$uname);
}
return $token;
}
/**
* 生成JWT
* @param int $userId
* @param string $uname
* @return string
* @throws \Exception
*/
private function makeToken(int $userId,string $uname): string
{
$signer = new Sha256();
$key = InMemory::plainText(config('jwt.secret'));
//
$config = Configuration::forSymmetricSigner($signer,$key);
$now = new DateTimeImmutable(); // 当前时间
//
$token = $config->builder()
// 签发人
->issuedBy('https://douyin.xingtongworld.com/')
// 受众
->permittedFor('https://douyin.xingtongworld.com/')
// JWT ID 编号 唯一标识
->identifiedBy($userId)
// 签发时间
->issuedAt($now)
// 在1分钟后才可使用
// ->canOnlyBeUsedAfter($now->modify('+1 minute'))
// 过期时间1小时
->expiresAt($now->modify('+1 hour'))
// 自定义uid 额外参数
->withClaim('uid', $userId)
->withClaim('name',$uname)
// 自定义header 参数
// ->withHeader('foo', 'bar')
// 生成token
->getToken($config->signer(), $config->signingKey());
return $token->toString();
} }
} }

4
composer.json

@ -23,13 +23,15 @@
"topthink/think-view": "^1.0", "topthink/think-view": "^1.0",
"topthink/think-captcha": "^3.0", "topthink/think-captcha": "^3.0",
"aliyuncs/oss-sdk-php": "^2.3", "aliyuncs/oss-sdk-php": "^2.3",
"firebase/php-jwt": "6.4",
"qcloud/cos-sdk-v5": "^2.0", "qcloud/cos-sdk-v5": "^2.0",
"qiniu/php-sdk": "^7.2", "qiniu/php-sdk": "^7.2",
"alibabacloud/client": "^1.5", "alibabacloud/client": "^1.5",
"jianyan74/php-excel": "^1.0", "jianyan74/php-excel": "^1.0",
"zhongshaofa/easy-admin": "^1.0.2", "zhongshaofa/easy-admin": "^1.0.2",
"ext-json": "*", "ext-json": "*",
"zhongshaofa/thinkphp-log-trace": "^1.0" "zhongshaofa/thinkphp-log-trace": "^1.0",
"lcobucci/jwt": "3.4"
}, },
"require-dev": { "require-dev": {
"symfony/var-dumper": "^4.2", "symfony/var-dumper": "^4.2",

Loading…
Cancel
Save