API接口JWT方式的Token认证(上),服务器(Laravel)的实现

简介: API接口JWT方式的Token认证(上),服务器(Laravel)的实现 最近在开发一个 Android 程序,需要做用户登录和认证功能,另外服务器用的是 Laravel 框架搭建的。

API接口JWT方式的Token认证(上),服务器(Laravel)的实现

最近在开发一个 Android 程序,需要做用户登录和认证功能,另外服务器用的是 Laravel 框架搭建的。最终决定用 JWT 实现API接口的认证。

JWT 是 Json Web Tokens 的缩写,与传统 Web 的 Cookies 或者 Session 方式的认证不同的是,JWT 是无状态的,服务器上不需要对 token 进行存储,也不需要和客户端保持连接。而 JWT 的 token 分3个部分,首先是头部 ,表明这是一个JWT,并指明加密方式,第二部分是负载,其中可以包含 账户名、ID、邮箱等用户信息,同时也包含了token到期时间,以 Unix 时间戳的方式记录,头部和负载都会进行 base64 编码,最后一部分是签名,用来验证负载的信息是否正确。

服务器上会保存一个全局 JWT_SECRET ,用于生成 token 和验证 token。在用户登录成功后,服务器从数据库获取用户的相关信息,计算出 token 到期时间,生成头部和负载并编码,再将前面的内容使用 JWT_SECRET 进行加密,生成签名,最后将3个部分合并返回给客户端。

客户端访问需要认证的客户端时,在 Http 请求头部加上 Authrization 字段,内容为 Bearer 加 token。服务器收到请求后,利用 JWT_SECRET 验证 token 是否合法,从负载中提取到期时间确认 token 是否过期,再从 token 提取用户信息,与数据库进行对比。如果这些都通过的话就可以进行后续操作了。

这里指大概介绍一下 JWT 的特点和验证流程,更详细的介绍大家可以自行搜索,或者访问 https://jwt.io/introduction/ 。

先上代码:
https://github.com/zhongchenyu/jokes-laravel
因为后续代码可能会做重构,本文所介绍的代码保存在 demo2 分支,请 checkout demo2

服务器代码实现

我们从一个空的 Laravel 项目开始着手,这里假设通过 laravel new project_name 命令安装了一个空的项目,并且完成了初始化配置,已经可以访问一些简单的测试 API了。下面开始搞 JWT。

1. 安装 JWT 库

首先通过 composer 安装 PHP 的 JWT 库:
composer require tymon/jwt-auth 0.5.*

在 config/app.php 下添加 JWTAuthServiceProvider:

'providers' => [

        /*
         * Laravel Framework Service Providers...
         */              
        ...
        Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class
    ],
AI 代码解读

也是在 config/app.php 下,注册门面:

'aliases' => [
        ...
        'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class,
        'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class,
    ],
AI 代码解读

发布 JWT 的配置文件到 config/jwt.php :

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"
AI 代码解读
  • 1

生成 JWT_SECRET,执行命令php artisan jwt:generate ,
会在 config/jwt.php 下生成'secret' => env('JWT_SECRET', 'UCDncib***wOY6gj0sD'), ,从 .env 的 JWT_SECRET 取值,如果没有再取后面的默认值,因为 config/jwt.php 是要随着 Git 版本发布的,所有最好在不同的环境上分别执行命令来生成 secret ,并且保持到 .env 文件中, .env 文件默认是 gitignore 的。

这样 JWT 库就安装好可以使用了。

2. 初始化数据库

首先创建好数据库,并修改 .env 文件中相关的值:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=jokes
DB_USERNAME=homestead
DB_PASSWORD=secret
AI 代码解读

这是数据库还是空的,没有任何 table,需要先进行数据库迁移。要做用户认证,肯定需要一个用户表,这个其实 Laravel 在已经帮我们做好的,在 database/migrations 下面已经生成了迁移文件:
migrations

看一下 create_users_table.php 的代码,创建一个 users 表,包含 id、name、email、password等列。

public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }
AI 代码解读

执行php artisan migrate 命令就会在 Jokes 数据库下创建好 users
表了。

mysql> show columns from users;
+----------------+------------------+------+-----+---------+----------------+
| Field          | Type             | Null | Key | Default | Extra          |
+----------------+------------------+------+-----+---------+----------------+
| id             | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name           | varchar(255)     | NO   |     | NULL    |                |
| email          | varchar(255)     | NO   | UNI | NULL    |                |
| password       | varchar(255)     | NO   |     | NULL    |                |
| remember_token | varchar(100)     | YES  |     | NULL    |                |
| created_at     | timestamp        | YES  |     | NULL    |                |
| updated_at     | timestamp        | YES  |     | NULL    |                |
+----------------+------------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)
AI 代码解读

对应的 Model 也已经自动创建好了,就是 app/User.php 文件。

3. 实现注册 API

users table 创建好后,当然是要生成 user 数据了,可以用 seeder 来生成测试用的 Faker 数据,初始代码也基本完成了 users 的 seeder。不过我们直接实现注册 API,通过 API 来创建数据。

在 Routes/api.php 下增加一条路由,这里我们使用的是 Dingo/Api :

$api->post('register', 'Auth\RegisterController@register');
AI 代码解读
  • 1

访问 register 路径,会调用 Auth\RegisterController.php 控制器下的 register 方法,看下代码:

protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|min:6' //|confirmed' 
        ]);
    }

    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => bcrypt($data['password']),
        ]);
    }

  public function register(Request $request)
  {
    $this->validator($request->all())->validate();

    $user = $this->create($request->all());
    $token = JWTAuth::fromUser($user);
    return ["token" => $token];
  }
AI 代码解读

其实大部分代码 Laravel 已经自动生成好了,但是由于原来的代码是用于 Web 注册的,注册成功后会重定向到登录页面,但是我们是给 API 做认证,所有就把这块代码改一下。
validator 方法是用来验证 Http 请求参数的。

'name' => 'required|string|max:255' 表示 name 是必须的,并且是最大长度255的字符串。

'email' => 'required|string|email|max:255|unique:users' 表示 email 是必须的,为最长255的邮箱格式的字符串,并且要和 users 数据库中的email不重复。

'password' => 'required|string|min:6' 表示 password是必须的,为最短6位的字符串,也可以加上 confirmed,表示需要二次确认,在请求参数中要在加上 password_confirmation ,并且和 password 是相同的才能通过验证,这里我们就先不用这个确认了。

create 方法将注册的用户信息写到数据库的 users table 中,其中 password 是经过加密存储的。

在 register 方法中, 先调用 validator,检查请求参数是否合法,通过后调用 create 将此用户数据写入数据库,在根据用户信息生成一个 token,返回给客户端。

测试一下,注册成功,返回 token:
这里写图片描述

mysql> select id,name,email,password from users where email = 'user6@user.com' ;
+----+---------+----------------+--------------------------------------------------------------+
| id | name    | email          | password                                                     |
+----+---------+----------------+--------------------------------------------------------------+
|  9 | user666 | user6@user.com | $2y$10$YCj55dl7ByyRP4x6znfM0.6Xsj9ScwF6d5czn1t4RZ59bOQgg0ST6 |
+----+---------+----------------+--------------------------------------------------------------+
1 row in set (0.00 sec)
AI 代码解读

4. 实现登录 API

首先在 Routes/api.php 下添加路由:
$api->get('login', 'Auth\AuthenticateController@authenticate');

看下 Auth\AuthenticateController 下的 authenticate 方法:

public function authenticate(Request $request)
  {   
    $credentials = $request->only('email', 'password');
    try {     
      if (! $token = JWTAuth::attempt($credentials)) {
        return response()->json(['error' => 'invalid_credentials'], 401);
      }
    } catch (JWTException $e) {
      return response()->json(['error' => 'could_not_create_token'], 500);
    }
    $user = User::where('email', $credentials['email'])->first();
    $userTransform = new UserTransformer();
    return ['user'=> $userTransform->transform($user), 'token' => $token];   
  }
AI 代码解读

代码也是基本初始化好了的,但是原来的代码登录后只返回 token,我们修改下,加上返回 User 信息。
先将 请求中的 email 和 password 存到 $credentials 中,再通过$token = JWTAuth::attempt($credentials) 检验 email 和 password,并尝试转换成 token,如果失败,则返回异常,如果成功则将 user 和 token 返回。

测试一下,用刚才的账号登录,成功获取到用户信息和 token:
这里写图片描述

5. 实现 token 认证

用户完成注册登录后,获取到 token,接下来就可以访问需要认证的 API 了,这里我们建一个简单的 API 来说明认证的实现方法。

假设用户需要获取通知信息 notices,服务器要求必须在登录后才能获取。

首先添加路由,这里用到了路由组和中间件(middleware):
在 app/kernel.php 文件下添加路由中间件:

protected $routeMiddleware = [
        ...
        'jwt.auth' => 'Tymon\JWTAuth\Middleware\GetUserFromToken',
        'jwt.refresh' => 'Tymon\JWTAuth\Middleware\RefreshToken',
    ];
AI 代码解读
$api->group(['middleware' => 'jwt.auth', 'providers' => 'jwt'], function ($api) { //
    $api->get('user', 'UserController@getUserInfo');
    $api->get('notices', 'NoticeController@index');
  });
AI 代码解读

此 group 下的所有路由,都需要先通过中间件处理,这里用的是 jwt.auth,及只有通过 jwt 认证之后,才能继续后面的访问。

这里只用来测试,NoticeController 下的 index 方法的返回数据直接是一句话:

public function index()
  {
    return ["content" => "This notice can be seen only after Auth"];
  }
AI 代码解读

测试一下用正确的 token 访问,在 Header 添加 Authrization 项,记住在 token 前加 Bearer ,可以获取数据:
这里写图片描述

测试用非法 token 访问,返回400错误:
这里写图片描述

测试过期 token 访问, 返回401错误:
这里写图片描述

同时我们还添加了 user 路由,JWTAuth::parseToken()->authenticate() 通过 token 获取用户:

class UserController extends Controller{
  public function getUserInfo(Request $request)
  {
    $user = JWTAuth::parseToken()->authenticate();
    return ( new UserTransformer())->transform($user);
  }
}
AI 代码解读

请求中添加 Authrization头,测试,这个 API 不仅用来获取用户信息,也作为 客户端存储的 token是否有效的检测 API:
这里写图片描述

至此,服务器上的认证相关的 API 接口就都准备好了,下篇文章将讲 Android 客户端的实现。

相关文章
深度评测 | 仅用3分钟,百炼调用满血版 Deepseek-r1 API,百万Token免费用,简直不要太爽。
仅用3分钟,百炼调用满血版Deepseek-r1 API,享受百万免费Token。阿里云提供零门槛、快速部署的解决方案,支持云控制台和Cloud Shell两种方式,操作简便。Deepseek-r1满血版在推理能力上表现出色,尤其擅长数学、代码和自然语言处理任务,使用过程中无卡顿,体验丝滑。结合Chatbox工具,用户可轻松掌控模型,提升工作效率。阿里云大模型服务平台百炼不仅速度快,还确保数据安全,值得信赖。
358199 71
深度评测 | 仅用3分钟,百炼调用满血版 Deepseek-r1 API,百万Token免费用,简直不要太爽。
12种API认证全场景解析:从Basic到OAuth2.0,哪个认证最适合你的业务?
在API认证领域,从简单的Key-Value到高级的OAuth2.0和JWT,共有12种主流认证方式。本文详解了每种方式的意义、适用场景及优劣,并通过认证方式矩阵对比常见工具(如Postman、Apifox)的支持情况。此外,还介绍了企业级安全功能,如密钥保险箱、动态令牌和合规审计。选择合适的认证方式不仅能提升安全性,还能大幅提高开发效率。未来,自动化认证矩阵或将成为API调试的核心趋势。
OpenRouter 推出百万 token 上下文 AI 模型!Quasar Alpha:提供完全免费的 API 服务,同时支持联网搜索和多模态交互
Quasar Alpha 是 OpenRouter 推出的预发布 AI 模型,具备百万级 token 上下文处理能力,在代码生成、指令遵循和低延迟响应方面表现卓越,同时支持联网搜索和多模态交互。
146 1
OpenRouter 推出百万 token 上下文 AI 模型!Quasar Alpha:提供完全免费的 API 服务,同时支持联网搜索和多模态交互
利用 AWS Signature:REST API 认证的安全指南
本文探讨了 AWS Signature 在保护 REST API 访问中的重要性,详解其工作原理,并提供 Java 和 Go 的实现示例。AWS Signature 通过加密技术确保请求安全,具备增强安全性、保障请求完整性、防范重放攻击及与 AWS 兼容等优势。文章还介绍了测试工具如 APIPost、Postman 和 cURL 的使用方法,帮助开发者验证实现效果。总结指出,采用 AWS Signature 可有效提升 API 安全性,增强用户信任并保护敏感数据。
为什么要为 REST API 添加认证
在现代Web服务中,REST API的通信安全至关重要。认证机制可验证用户身份、控制资源访问、保护数据并监控使用情况。Basic Auth(基本认证)是一种简单有效的方法,通过HTTP头部发送Base64编码的用户名和密码实现安全保护,但建议搭配HTTPS使用以避免漏洞。本文展示了如何用Java和Go语言实现Basic Auth,并介绍了APIPost、Curl和Postman等工具进行测试。开发者可通过这些方法确保API功能强大且安全可靠。
什么是用于 REST API 的 Bearer Token以及如何通过代码和工具进行调试
Bearer Token 是一种基于 OAuth 2.0 的身份验证机制,广泛应用于 REST API 的授权访问中。它通过在 HTTP 请求头中传递令牌,确保用户凭据安全传输并验证。本文深入解析了 Bearer Token 的概念、实现步骤及调试方法,包括其无状态特性、灵活性与安全性优势。同时,提供了 Java 实现示例和使用 Apipost、cURL 等工具测试的实践指导,帮助开发者掌握这一核心技能,保障 API 系统的安全与高效运行。
API 安全之认证鉴权
API 作为企业的重要数字资源,在给企业带来巨大便利的同时也带来了新的安全问题,一旦被攻击可能导致数据泄漏重大安全问题,从而给企业的业务发展带来极大的安全风险。
如何实现和调试REST API中的摘要认证(Digest Authentication)
本文介绍如何实现和调试REST API中的摘要认证(Digest Authentication),涵盖其原理、优势及Java和Go语言的实现示例。摘要认证通过哈希算法处理密码,避免明文传输风险,并使用nonce防止重放攻击,确保数据完整性。文中还提供了Postman、cURL和Insomnia等工具的测试方法,帮助开发者轻松验证API的安全性。总结指出,摘要认证相比基本认证更安全,适合需要高安全性的API应用。
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
109 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
OpenAI API深度解析:参数、Token、计费与多种调用方式
随着人工智能技术的飞速发展,OpenAI API已成为许多开发者和企业的得力助手。本文将深入探讨OpenAI API的参数、Token、计费方式,以及如何通过Rest API(以Postman为例)、Java API调用、工具调用等方式实现与OpenAI的交互,并特别关注调用具有视觉功能的GPT-4o使用本地图片的功能。此外,本文还将介绍JSON模式、可重现输出的seed机制、使用代码统计Token数量、开发控制台循环聊天,以及基于最大Token数量的消息列表限制和会话长度管理的控制台循环聊天。
1955 7

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等