zoukankan      html  css  js  c++  java
  • 【laravel】基于jwt实现用户认证

    安装及基础配置

    使用 composer 安装

    # 建议使用1.0以上版本
    composer require tymon/jwt-auth 1.*@rc

    进行一些配置

    有些文档会说要添加 TymonJWTAuthProvidersLaravelServiceProvider::class ,这只在 Laravel 5.4 及以下版本是必要的,更新的 Laravel 版本无需添加。

    还有一些文档说要添加 TymonJWTAuthProvidersJWTAuthServiceProvider 这是很久以前的 JWT 版本的(大概0.5.3 以前的版本)。

    发布配置文件

    # 这条命令会在 config 下增加一个 jwt.php 的配置文件
    php artisan vendor:publish --provider="TymonJWTAuthProvidersLaravelServiceProvider"

    生成加密密钥

    # 这条命令会在 .env 文件下生成一个加密密钥,如:JWT_SECRET=foobar
    php artisan jwt:secret

    更新你的模型

    如果你使用默认的 User 表来生成 token,你需要在该模型下增加一段代码

    <?php
    
    namespace App;
    
    use TymonJWTAuthContractsJWTSubject;
    use IlluminateNotificationsNotifiable;
    use IlluminateFoundationAuthUser as Authenticatable;
    
    class User extends Authenticatable implements JWTSubject    # 这里别忘了加
    {
        use Notifiable;
    
        // Rest omitted for brevity
    
        /**
         * Get the identifier that will be stored in the subject claim of the JWT.
         *
         * @return mixed
         */
        public function getJWTIdentifier()
        {
            return $this->getKey();
        }
    
        /**
         * Return a key value array, containing any custom claims to be added to the JWT.
         *
         * @return array
         */
        public function getJWTCustomClaims()
        {
            return [];
        }
    }

    注册两个 Facade

    这两个 Facade 并不是必须的,但是使用它们会给你的代码编写带来一点便利。

    config/app.php

    'aliases' => [
            ...
            // 添加以下两行
            'JWTAuth' => 'TymonJWTAuthFacadesJWTAuth',
            'JWTFactory' => 'TymonJWTAuthFacadesJWTFactory',
    ],

    如果你不使用这两个 Facade,你可以使用辅助函数 auth()

    auth() 是一个辅助函数,返回一个guard,暂时可以看成 Auth Facade。

    可以参考这篇文章——Laravel 辅助函数 auth 与 JWT 扩展详解

    // 如果你不用 Facade,你可以这么写
    auth('api')->refresh();
    // 用 JWTAuth Facade
    JWTAuth::parseToken()->refresh();

    两个 Facede 常用可使用方法,可以看文章后面的附录。

     修改 auth.php

    config/auth.php

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
    
        'api' => [
            'driver' => 'jwt',      // 原来是 token 改成jwt
            'provider' => 'users',
        ],
    ],

    注册一些路由

    注意:在 Laravel 下,route/api.php 中的路由默认都有前缀 api

    Route::group([
    
        'prefix' => 'auth'
    
    ], function ($router) {
    
        Route::post('login', 'AuthController@login');
        Route::post('logout', 'AuthController@logout');
        Route::post('refresh', 'AuthController@refresh');
        Route::post('me', 'AuthController@me');
    
    });

    创建 token 控制器

    php artisan make:controller AuthController

    AuthController

    值得注意的是 Laravel 这要用 auth('api') ,至于为什么,我另一篇关于 JWT 扩展详解的文章里有讲

    <?php
    
    namespace AppHttpControllers;
    
    use IlluminateSupportFacadesAuth;
    use AppHttpControllersController;
    
    class AuthController extends Controller
    {
        /**
         * Create a new AuthController instance.
         * 要求附带email和password(数据来源users表)
         * 
         * @return void
         */
        public function __construct()
        {
            // 这里额外注意了:官方文档样例中只除外了『login』
            // 这样的结果是,token 只能在有效期以内进行刷新,过期无法刷新
            // 如果把 refresh 也放进去,token 即使过期但仍在刷新期以内也可刷新
            // 不过刷新一次作废
            $this->middleware('auth:api', ['except' => ['login']]);
            // 另外关于上面的中间件,官方文档写的是『auth:api』
            // 但是我推荐用 『jwt.auth』,效果是一样的,但是有更加丰富的报错信息返回
        }
    
        /**
         * Get a JWT via given credentials.
         *
         * @return IlluminateHttpJsonResponse
         */
        public function login()
        {
            $credentials = request(['email', 'password']);
    
            if (! $token = auth('api')->attempt($credentials)) {
                return response()->json(['error' => 'Unauthorized'], 401);
            }
    
            return $this->respondWithToken($token);
        }
    
        /**
         * Get the authenticated User.
         *
         * @return IlluminateHttpJsonResponse
         */
        public function me()
        {
            return response()->json(auth('api')->user());
        }
    
        /**
         * Log the user out (Invalidate the token).
         *
         * @return IlluminateHttpJsonResponse
         */
        public function logout()
        {
            auth('api')->logout();
    
            return response()->json(['message' => 'Successfully logged out']);
        }
    
        /**
         * Refresh a token.
         * 刷新token,如果开启黑名单,以前的token便会失效。
         * 值得注意的是用上面的getToken再获取一次Token并不算做刷新,两次获得的Token是并行的,即两个都可用。
         * @return IlluminateHttpJsonResponse
         */
        public function refresh()
        {
            return $this->respondWithToken(auth('api')->refresh());
        }
    
        /**
         * Get the token array structure.
         *
         * @param  string $token
         *
         * @return IlluminateHttpJsonResponse
         */
        protected function respondWithToken($token)
        {
            return response()->json([
                'access_token' => $token,
                'token_type' => 'bearer',
                'expires_in' => auth('api')->factory()->getTTL() * 60
            ]);
        }
    }

     使用 token

    有两种使用方法:

    • 加到 url 中:?token=你的token
    • 加到 header 中,建议用这种,因为在 https 情况下更安全:Authorization:Bearer 你的token

    添加中间件保护的就需要使用 token进行访问

    可以使用的中间件有 auth、auth:api、jwt.auth、jwt.refresh、jwt.check、jwt.renew

    关于这些中间件之间有什么差别,可以看另一篇文章:Laravel 辅助函数 auth 与 JWT 扩展详解

    参考文档

  • 相关阅读:
    LeetCode OJ String to Integer (atoi) 字符串转数字
    HDU 1005 Number Sequence(AC代码)
    HDU 1004 Let the Balloon Rise(AC代码)
    HDU 1003 Max Sum(AC代码)
    012 Integer to Roman 整数转换成罗马数字
    011 Container With Most Water 盛最多水的容器
    010 Regular Expression Matching 正则表达式匹配
    007 Reverse Integer 旋转整数
    006 ZigZag Conversion
    005 Longest Palindromic Substring 最长回文子串
  • 原文地址:https://www.cnblogs.com/jxl1996/p/10354010.html
Copyright © 2011-2022 走看看