基于 JWT-Auth 实现 API 验证

如果想要了解其生成Token的算法原理,请自行查阅相关资料

需要提及的几点:

  • 使用session存在的问题:

    • session和cookie是为了解决http无状态的方案。session是用户保存在服务器中的状态信息,cookie中则保存jsessionId,请求服务器时,服务器读取jsessionId从而确定用户的身份信息,而session+cookie用在restful接口上破坏了其“无状态”的特性,session运行时都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。这也是restful最致力于通过“无状态”解决的问题。如果使用session,那么restful也就没有什么意义了
    • session降低了系统扩展性。用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡器的能力。这也意味着限制了应用的扩展能力
    • cookie不安全,很容易导致跨站请求伪造攻击(CSRF)
  • token存在的问题:
    • 如,如何确定token的过期时间?如果token的有效期过短,很容易造成用户用着用着就掉线的情况,降低用户体验。但目前看来好像并没有太好的办法,只能尽量延长token的有效期,或者每隔一次前端自动向服务端请求一次token
  • 基于 JWT-Auth 的 token 验证体系

    (亲测,希望这篇文章让大家少入坑)

  1. 运行软件版本

    • laravel 5.5
  2. 安装 JWT-Auth 扩展包

    composer require tymon/jwt-auth "1.5.*"

  3. 安装完后在配置文件config/app.php 中添加注册服务提供者和别名:
    ...‘providers‘ => [    ...    Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class,]...‘aliases‘ => [    ...    ‘JWTAuth‘ => Tymon\JWTAuth\Facades\JWTAuth::class,]
  4. 发布资源配置
    php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"
  5. 运行以下命令生成密钥key在生成的config/jwt.php
    // 如果运行后报错,提示ERROR:Method Tymon\JWTAuth\Commands\JWTGenerateCommand::handle() does not exist,将vendor\tymon\jwt-auth\src\Commands\JWTGenerateCommand.php文件中的 fire() 方法修改为 handle()即可正常生成秘钥php artisan jwt:generate
  6. 编辑 app/Http/Kernel.php 添加 jwt.auth 和 jwt.refresh 到应用路由中间件数组:
    protected $routeMiddleware = [    ...    ‘jwt.auth‘ => \Tymon\JWTAuth\Middleware\GetUserFromToken::class,//    ‘jwt.refresh‘ => \Tymon\JWTAuth\Middleware\RefreshToken::class,];
  7. JWTAuth 自身中间件\Tymon\JWTAuth\Middleware\GetUserFromToken 中包含了对生成token的各类情况的验证,以及异常的抛出。下面是其底层验证类GetUserFromToken::class
    // file_path : vendor\tymon\jwt-auth\src\Middleware\GetUserFromToken.php<?php?/* * This file is part of jwt-auth. * * (c) Sean Tymon <[email protected]> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */?namespace Tymon\JWTAuth\Middleware;?use Tymon\JWTAuth\Exceptions\JWTException; //验证异常类use Tymon\JWTAuth\Exceptions\TokenExpiredException;//token过期异常验证类?class GetUserFromToken extends BaseMiddleware{    /**     * Handle an incoming request.     *     * @param  \Illuminate\Http\Request  $request     * @param  \Closure  $next     * @return mixed     */    public function handle($request, \Closure $next)    {        if (! $token = $this->auth->setRequest($request)->getToken()) {            return $this->respond(‘tymon.jwt.absent‘, ‘token_not_provided‘, 400);        }?        try {            $user = $this->auth->authenticate($token);        } catch (TokenExpiredException $e) {            return $this->respond(‘tymon.jwt.expired‘, ‘token_expired‘, $e->getStatusCode(), [$e]);        } catch (JWTException $e) {            return $this->respond(‘tymon.jwt.invalid‘, ‘token_invalid‘, $e->getStatusCode(), [$e]);        }?        if (! $user) {            return $this->respond(‘tymon.jwt.user_not_found‘, ‘user_not_found‘, 404);        }?        $this->events->fire(‘tymon.jwt.valid‘, $user);?        return $next($request);    }}

    其中,调用的respond 的方法在vendor\tymon\jwt-auth\src\Middleware\BaseMiddleware.php文件中

     /**     * Fire event and return the response.     *     * @param  string   $event     * @param  string   $error     * @param  int  $status     * @param  array    $payload     * @return mixed     */    protected function respond($event, $error, $status, $payload = [])    {        $response = $this->events->fire($event, $payload, true);?        return $response ?: $this->response->json([‘error‘ => $error], $status);    }

    可看到,当出现异常需要返回错误信息时,会连带返回一个fire event 的警告事件对象,这里不做详述。

  8. 由底层代码中,可以了解到,我们如果想自定义自己所需要的验证方法,可以将这GetUserFromToken::class 内容复制到我们自己自定义的中间件中。比如:
    • 创建自定义的验证中间件App\Http\Middleware\JwtAuth.php

      php artisan make:middleware JwtAuth
    • 全部复制到自定义的中间件中后,校验下中间件中需要的类是否应用完全,命名空间是否正确等等,检查无误后根据需要自行定义需要的验证功能。
      // demo namespace App\Http\Middleware;?use Tymon\JWTAuth\Exceptions\JWTException;use Tymon\JWTAuth\Exceptions\TokenExpiredException;use Closure;use Tymon\JWTAuth\Middleware\BaseMiddleware;?class JwtAuth extends BaseMiddleware{    public function handle($request, \Closure $next)    {        if (! $token = $this->auth->setRequest($request)->getToken()) {            return $this->respond(‘tymon.jwt.absent‘, ‘token_not_provided‘, 400);        }?        try {            $user = $this->auth->authenticate($token);        } catch (TokenExpiredException $e) {            return $this->respond(‘tymon.jwt.expired‘, ‘token_expired‘, $e->getStatusCode(), [$e]);        } catch (JWTException $e) {            return $this->respond(‘tymon.jwt.invalid‘, ‘token_invalid‘, $e->getStatusCode(), [$e]);        }?        if (! $user) {            return $this->respond(‘tymon.jwt.user_not_found‘, ‘user_not_found‘, 404);        }?        $this->events->fire(‘tymon.jwt.valid‘, $user);?        return $next($request);    }}
    • 定义完成后将自定义的中间件放入app\Http\Kernel.php的中间件数组中。
       protected $routeMiddleware = [    ...        //‘jwt.auth‘ => \Tymon\JWTAuth\Middleware\GetUserFromToken::class,        ‘jwt.auth_self‘ => \App\Http\Middleware\JwtAuth::class    ];
    • 添加好后,即可在routes/api.php 中对需要控制的api路由进行验证控制
      Route::group([‘middleware‘=>‘jwt.auth_self‘],function(){    // 需要控制的api路由    // ... code});
  9. 我们现在可以对请求来的路由进行token的验证,那么接下来我们就需要生成这个token,让后续访问中间件中的请求路由都携带这个token就能实现验证。这里要提一下在安装JWT-Auth过程中生成的配置文件config/jwt.php
    <?php    return [    ...    /*    |--------------------------------------------------------------------------    | User Model namespace    |--------------------------------------------------------------------------    |    | Specify the full namespace to your User model.    | e.g. ‘Acme\Entities\User‘    |    */    // 设置你的用户model,默认为laravel自带的 User model    ‘user‘ => ‘App\User‘,]

    如果需求需要,可在配置文件中修改用户mode ,但配置的model 中需要引用Illuminate\Foundation\Auth\User as Authenticatable,并继承,写法和User model一致

  10. 具体的请求登录以及获取token信息,登出等功能实现,可参考此文章

    Laravel 5 中使用 JWT(Json Web Token) 实现基于API的用户认证,这里简单提及下常用到的有关其token的方法

    <?php    namespace App\Http\Controller;
    
    use Tymon\JWTAuth\JWTAuth;
    
    class Auth{        public function test (JWTAuth $JWTAuth){                        // 获取请求携带中的token            $token = $JWTAuth -> getToken();            // 获取token中的用户信息            $user = $JWTAuth -> parseToken() -> authenticate();            // 销毁此次生成的token            $JWTAuth->setToken( $JWTAuth->getToken() )->invalidate();            // 自定义生成token,如果需要            $JWTAuth->setToken(‘foo.bar.baz‘);        }    }

原文地址:https://www.cnblogs.com/liwei-17/p/9249546.html

时间: 2024-07-31 12:36:26

基于 JWT-Auth 实现 API 验证的相关文章

基于JWT的web api身份验证及跨域调用实践

随着多终端的出现,越来越多的站点通过web api restful的形式对外提供服务,很多网站也采用了前后端分离模式进行开发,因而在身份验证的方式上可能与传统的基于cookie的Session Id的做法有所不同,除了面临跨域提交cookie的烦人问题外,更重要的是,有些终端可能根本不支持cookie. Json Web Token(jwt)是一种不错的身份验证及授权方案,简单的说就是调用端调用api时,附带上一个由api端颁发的token,以此来验证调用者的授权信息.但由于时间关系,不对jwt

asp.net core 2.0 web api基于JWT自定义策略授权

JWT(json web token)是一种基于json的身份验证机制,流程如下: 通过登录,来获取Token,再在之后每次请求的Header中追加Authorization为Token的凭据,服务端验证通过即可能获取想要访问的资源.关于JWT的技术,可参考网络上文章,这里不作详细说明, 这篇博文,主要说明在asp.net core 2.0中,基于jwt的web api的权限设置,即在asp.net core中怎么用JWT,再次就是不同用户或角色因为权限问题,即使援用Token,也不能访问不该访

基于Volley,Gson封装支持JWT无状态安全验证和数据防篡改的GsonRequest网络请求类

这段时间做新的Android项目的客户端和和REST API通讯框架架构设计,使用了很多新技术,最终的方案也相当简洁优雅,客户端只需要传Java对象,服务器端返回json字符串,自动解析成Java对象, 无状态安全验证基于JWT实现,JWT规范的细节可以参考我前面的文章.JWT的token和数据防篡改签名统一放在HTTP Header中,这样就实现了对请求内容和返回结果的无侵入性,服务器端也可以在全局过滤器中统一处理安全验证. Android客户端使用了Volley网络请求框架和Gson解析库,

用户认证:基于jwt和session的区别和优缺点

背景知识: Authentication和Authorization的区别: Authentication:用户认证,指的是验证用户的身份,例如你希望以小A的身份登录,那么应用程序需要通过用户名和密码确认你真的是小A. Authorization:授权,指的是确认你的身份之后提供给你权限,例如用户小A可以修改数据,而用户小B只能阅读数据. 由于http协议是无状态的,每一次请求都无状态.当一个用户通过用户名和密码登录了之后,他的下一个请求不会携带任何状态,应用程序无法知道他的身份,那就必须重新认

掌握基于 JWT 实现的 Token 身份认证

引语 最近正好在独立开发一个后台管理系统,涉及到了基于Token的身份认证,自己边学边用边做整理和总结,对基于JWT实现的Token的身份认证做一次相对比较全面的认识. 一.基于session的跨域身份验证 Internet服务无法与用户身份验证分开.一般过程如下. 用户向服务器发送用户名和密码. 验证服务器后,相关数据(如用户角色,登录时间等)将保存在当前会话中. 服务器向用户返回session_id,session信息都会写入到用户的Cookie. 用户的每个后续请求都将通过在Cookie中

WebApi基于Token和签名的验证

最近一段时间在学习WebApi,涉及到验证部分的一些知识觉得自己并不是太懂,所以来博客园看了几篇博文,发现一篇讲的特别好的,读了几遍茅塞顿开(都闪开,我要装逼了),刚开始读有些地方不理解,所以想了很久,因此对原文中省略的部分这里做一点个人的理解和补充,非常基础,知道的园友就不需要了,只是帮助初次学习的园友理解.原文传送门: http://www.cnblogs.com/MR-YY/p/5972380.html#!comments 本篇博文中的所有代码均来自上述链接,如果你觉得有帮助,请点击链接给

基于Hadoop的密码安全级别验证

学习Hadoop有一段时间了,期间写过很多Demo,都是针对单个知识点做的验证,今天写个完整的应用程序——基于Hadoop的密码安全级别验证. 在很多网站上注册用户时输入密码都会在下方提示密码安全级别.如下图所示: 一般通过算法得出密码安全等级,但是公认的最不安全密码 passw0rd! 也会被认为安全程度强. 我想起若干年前的某论坛密码泄露事件,于是从网上找到了当年的数据(全是文本文件,每行一条记录,正好可以用Hadoop处理),开始着手开发此程序. 程序分成三部分: Hadoop集群分析每个

Laravel 5.4+ Dingo +Jwt 快速搭建 API系统

刚进入新公司,比较忙,只能抽时间来写写比较简短的博文总结,还望见谅. 最近公司要从实业转型线上,决定用laravel 来做快速开发,而一些同事之前没有用过laravel,尤其是api 的快速搭建,一致想让我把搭建过程给分享出来,此为背景----也算是治疗懒癌的动机 ^_^ ~~~ 搭建过程记录 : 我们采用 laravel 5.4 ,因为5.6好像比这更简洁,等我使用过后再来分享__创建 laravel 项目 composer create-project --prefer-dist larav

Nginx集群之基于Redis的WebApi身份验证

目录 1       大概思路... 1 2       Nginx集群之基于Redis的WebApi身份验证... 1 3       Redis数据库... 2 4       Visualbox虚拟机ubuntu下的redis部署... 3 5       编写.NET WebApi的OnAuthorization身份验证... 6 6       编写.NET WebApi的ActionFilterAttribute令牌验证... 8 7       编写.NET WebApi的服务端.