Yii2 基础版实现 Token 认证 API 服务的完整框架方案

以下是一个基于 Yii2 基础版实现 Token 认证 API 服务的完整框架方案,包含 JWT 实现和完整代码:

1. 环境准备

composer create-project --prefer-dist yiisoft/yii2-app-basic yii2-api
cd yii2-api

2. 安装必要扩展

composer require firebase/php-jwt
composer require yiisoft/yii2-faker

3. 数据库配置 (config/db.php)

return ['class' => 'yii\db\Connection','dsn' => 'mysql:host=localhost;dbname=yii2_api','username' => 'root','password' => '','charset' => 'utf8',
];

4. 用户模型 (models/User.php)

<?php
namespace app\models;use Yii;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;class User extends ActiveRecord implements IdentityInterface
{const STATUS_ACTIVE = 10;public static function tableName(){return '{{%user}}';}public function rules(){return [['status', 'default', 'value' => self::STATUS_ACTIVE],['status', 'in', 'range' => [self::STATUS_ACTIVE]],];}// 实现 IdentityInterface 方法public static function findIdentity($id){return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);}public static function findIdentityByAccessToken($token, $type = null){try {$secret = Yii::$app->params['jwtSecret'];$decoded = JWT::decode($token, new Key($secret, 'HS256'));return static::findOne(['id' => $decoded->sub, 'status' => self::STATUS_ACTIVE]);} catch (\Exception $e) {return null;}}public function getId(){return $this->id;}public function getAuthKey(){return null; // 不使用 cookie 登录}public function validateAuthKey($authKey){return false; // 不使用 cookie 登录}// 生成 JWT Tokenpublic function generateJwt(){$secret = Yii::$app->params['jwtSecret'];$currentTime = time();$payload = ['iss' => 'yii2-api-server', // 签发者'aud' => 'api-client',      // 接收方'iat' => $currentTime,      // 签发时间'exp' => $currentTime + 86400, // 过期时间 (24小时)'sub' => $this->id,         // 用户ID];return JWT::encode($payload, $secret, 'HS256');}// 验证密码public function validatePassword($password){return Yii::$app->security->validatePassword($password, $this->password_hash);}// 设置密码public function setPassword($password){$this->password_hash = Yii::$app->security->generatePasswordHash($password);}
}

5. 登录表单模型 (models/LoginForm.php)

<?php
namespace app\models;use yii\base\Model;class LoginForm extends Model
{public $username;public $password;public $rememberMe = true;private $_user;public function rules(){return [[['username', 'password'], 'required'],['rememberMe', 'boolean'],['password', 'validatePassword'],];}public function validatePassword($attribute){if (!$this->hasErrors()) {$user = $this->getUser();if (!$user || !$user->validatePassword($this->password)) {$this->addError($attribute, '用户名或密码错误');}}}public function login(){if ($this->validate()) {return $this->getUser()->generateJwt();}return false;}protected function getUser(){if ($this->_user === null) {$this->_user = User::findByUsername($this->username);}return $this->_user;}
}

6. API 控制器基类 (controllers/ApiController.php)

<?php
namespace app\controllers;use yii\rest\Controller;
use yii\filters\auth\HttpBearerAuth;
use yii\web\UnauthorizedHttpException;class ApiController extends Controller
{public function behaviors(){$behaviors = parent::behaviors();// 启用 Bearer Token 认证$behaviors['authenticator'] = ['class' => HttpBearerAuth::className(),'optional' => $this->authOptional(), // 排除不需要认证的方法];return $behaviors;}protected function authOptional(){return [];}// 认证失败处理public function beforeAction($action){if (!parent::beforeAction($action)) {return false;}if (Yii::$app->user->isGuest && !in_array($action->id, $this->authOptional())) {throw new UnauthorizedHttpException('请提供有效的认证令牌');}return true;}
}

7. 认证控制器 (controllers/AuthController.php)

<?php
namespace app\controllers;use app\models\LoginForm;
use yii\rest\Controller;
use yii\web\ServerErrorHttpException;class AuthController extends Controller
{public function actionLogin(){$model = new LoginForm();$model->load(Yii::$app->request->post(), '');if ($token = $model->login()) {return ['token' => $token];} elseif ($model->hasErrors()) {return $model;} else {throw new ServerErrorHttpException('登录失败,请稍后重试');}}
}

8. 受保护 API 示例 (controllers/UserController.php)

<?php
namespace app\controllers;class UserController extends ApiController
{protected function authOptional(){return []; // 所有操作都需要认证}public function actionProfile(){$user = Yii::$app->user->identity;return ['id' => $user->id,'username' => $user->username,'email' => $user->email,'created_at' => date('Y-m-d H:i:s', $user->created_at),];}public function actionSecureData(){return ['message' => '这是受保护的API数据','timestamp' => time(),'user_id' => Yii::$app->user->id];}
}

9. 配置参数 (config/params.php)

return ['adminEmail' => 'admin@example.com','jwtSecret' => 'your-secret-key-here', // 替换为强密钥
];

10. 配置 URL 规则 (config/web.php)

'urlManager' => ['enablePrettyUrl' => true,'showScriptName' => false,'rules' => ['POST /auth/login' => 'auth/login','GET /user/profile' => 'user/profile','GET /secure-data' => 'user/secure-data',// RESTful API 路由示例['class' => 'yii\rest\UrlRule', 'controller' => 'api'],],
],

11. 数据库迁移

创建用户表迁移:

yii migrate/create create_user_table
// migrations/mxxxxxx_xxxxxx_create_user_table.php
public function safeUp()
{$this->createTable('{{%user}}', ['id' => $this->primaryKey(),'username' => $this->string(255)->notNull()->unique(),'email' => $this->string(255)->notNull()->unique(),'password_hash' => $this->string(255)->notNull(),'status' => $this->smallInteger()->notNull()->defaultValue(10),'created_at' => $this->integer()->notNull(),'updated_at' => $this->integer()->notNull(),]);
}public function safeDown()
{$this->dropTable('{{%user}}');
}

运行迁移:

yii migrate/up

12. 测试用户生成 (commands/SeedController.php)

yii migrate/create create_seed_controller
<?php
namespace app\commands;use yii\console\Controller;
use app\models\User;class SeedController extends Controller
{public function actionIndex(){$user = new User();$user->username = 'testuser';$user->email = 'test@example.com';$user->setPassword('password123');$user->created_at = time();$user->updated_at = time();if ($user->save()) {echo "测试用户创建成功\n";echo "用户名: testuser\n";echo "密码: password123\n";} else {print_r($user->errors);}}
}

运行种子:

yii seed

使用示例

1. 获取 Token
curl -X POST http://api.example.com/auth/login \-H "Content-Type: application/json" \-d '{"username":"testuser", "password":"password123"}'

响应:

{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."}
2. 访问受保护 API
curl -X GET http://api.example.com/user/profile \-H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."

响应:

{"id": 1,"username": "testuser","email": "test@example.com","created_at": "2023-05-15 10:30:00"
}

安全增强建议

  1. HTTPS 强制使用

    // config/web.php
    'components' => ['request' => ['cookieValidationKey' => 'your-key','enableCsrfValidation' => false, // API 通常禁用 CSRF'parsers' => ['application/json' => 'yii\web\JsonParser',],],
    ],
    
  2. 速率限制

    // 在控制器中添加
    use yii\filters\RateLimiter;public function behaviors()
    {$behaviors = parent::behaviors();$behaviors['rateLimiter'] = ['class' => RateLimiter::class,];return $behaviors;
    }
    
  3. 刷新令牌机制

    • 实现双令牌系统(access token + refresh token)
    • access token 设置较短有效期(如 30 分钟)
    • 使用 refresh token 获取新 access token
  4. 敏感操作日志

    • 记录所有关键操作(登录、数据修改等)
    • 包含用户 ID、IP 地址和时间戳

这个框架提供了完整的 JWT 认证实现,包含了用户管理、Token 生成与验证、API 保护等核心功能,可以直接作为基础进行扩展开发。

通义千问-回答
实操成功
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/83977.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/83977.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

主流版本控制工具Git vs Perforce P4:架构模式、性能、大文件管理及分支管理对比详解

Git和Perforce P4是两个强大的源代码管理工具&#xff0c;各有其独特的功能优势与适用场景。 本文中&#xff0c;Perforce中国授权合作伙伴-龙智将从架构设计、性能表现、文件管理及分支策略等维度&#xff0c;为您详细解析两者的关键差异&#xff0c;帮助您根据团队需求&…

文件系统2(Linux下)

1 挂载分区 文件系统1中已经知道了能够根据inode号在指定分区找文件了&#xff0c;也已经能根据目录文件内容&#xff0c;找指定的inode了&#xff0c;在指定的分区内&#xff0c;就可以对文件进行操作了。但是还有几个问题&#xff0c;那就是inode是不能跨分区的&#xff0c;…

Leetcode-​2537. 统计好子数组的数目​

Problem: 2537. 统计好子数组的数目 思路 滑动窗口 解题过程 思路&#xff1a; 使用滑动窗口来维护子数组&#xff0c;并通过组合计数动态调整满足条件的数对数目。具体来说&#xff0c;我们维护一个窗口[l,r]&#xff0c;使得窗口内相同元素的对数至少为 k&#xff0c;并计算…

js手写代码篇--手写Object.assign

19、Object.assign 作用&#xff1a; Object.assign的作用是将源对象的所有可枚举属性复制到目标对象中。它返回目标对象。 const obj1 { a: 1, b: 2 };const obj2 { b: 3, c: 4 };const obj3 { d: 5 };const target {};Object.assign(target, obj1, obj2, obj3);console…

使用 C/C++ 和 OpenCV 构建智能停车场视觉管理系统

使用 C 和 OpenCV 构建智能停车场视觉管理系统 本文将详细介绍如何利用 C 和 OpenCV 库&#xff0c;从零开始创建一个智能停车场管理系统。该系统通过摄像头捕捉的画面&#xff0c;能自动完成两项核心任务&#xff1a; 车位识别&#xff1a;通过检测地面上的黄色停车线&#…

服务器静态ip,网关不能占用*.*.*.1

网关不能占用*.*.*.1.1 通常用于运行关键服务&#xff08;如DHCP、NAT、DNS代理&#xff09;&#xff0c;.1 是网络世界的"VIP包厢"&#xff0c;普通用户强闯只会被"请出"。

自然语言处理【NLP】—— CBOW模型

文章目录 引言一、CBOW模型概述1.1 什么是CBOW模型1.2 CBOW vs Skip-gram 二、CBOW模型原理详解2.1 模型架构2.2 数学原理2.3 训练过程 三、CBOW的PyTorch实现四、CBOW模型的应用与优化4.1 典型应用场景4.2 性能优化技巧 五、CBOW的局限性六、结语 引言 在自然语言处理(NLP)领…

为MTK 9300开发板移植Linux系统(以Debian为例)的详细技术指南

以下是为MTK 9300开发板移植Linux系统(以Debian为例)的详细技术指南,涵盖环境搭建、内核移植、驱动适配(摄像头/显示器/WiFi)、系统集成与优化。 MTK 9300开发板Linux系统移植全流程指南 1 项目概述 1.1 硬件平台 SoC:MediaTek MTK9300 (ARMv8-A架构,4Cortex-A78 + 4C…

Java Lambda 表达式与 Stream API 全解析:从基础到进阶

以下是对您博客内容的优化版本&#xff0c;在保留原有核心内容的基础上&#xff0c;补充了Lambda表达式及Stream API的完整方法体系&#xff0c;并通过结构化排版和扩展说明提升可读性。 Java Lambda表达式与Stream API全解析&#xff1a;从基础到进阶 一、Lambda表达式与Str…

Let’s Encrypt(乐此加密) 免费SSL证书申请

一、前言 腾讯云、阿里云等平台都支持免费的SSL证书申请&#xff0c;但只支持单域名SSL证书申请&#xff0c;不支持泛域名证书申请&#xff0c;而且每年只有20张免费证书额度&#xff0c;自2024年4月25日之起免费申请的证书只有3个月有效期。域名比较多的情况下&#xff0c;更新…

SQLite3 性能优化

在嵌入式开发和轻量级应用场景中&#xff0c;SQLite3 作为轻量级数据库引擎&#xff0c;凭借其无需独立服务器、部署便捷等特点被广泛应用。然而&#xff0c;当面对大量数据的高速读写需求时&#xff0c;默认配置下的 SQLite3 性能往往难以满足要求。本文将从数据库配置调整、W…

零基础设计模式——行为型模式 - 状态模式

第四部分&#xff1a;行为型模式 - 状态模式 (State Pattern) 我们继续学习行为型模式&#xff0c;接下来是状态模式。这个模式允许一个对象在其内部状态改变时改变它的行为&#xff0c;对象看起来就像是改变了它的类。 核心思想&#xff1a;允许一个对象在其内部状态改变时改…

面向对象面试题集合

前言 记录面向对象面试题相关内容&#xff0c;方便复习及查漏补缺 题1.简述面向对象&#xff1f;主要特征是什么&#xff1f; 面向对象编程&#xff08;Object-Oriented Programming&#xff0c;简称OOP&#xff09;是一种以“对象”为核心的编程范式&#xff0c;通过将现实…

二十一、【用户管理与权限 - 篇三】角色管理:前端角色列表与 CRUD 实现

【用户管理与权限 - 篇三】角色管理:前端角色列表与 CRUD 实现 前言准备工作第一部分:更新 API 服务以包含角色管理第二部分:添加角色管理页面的路由和侧边栏入口第三部分:实现角色列表页面第四部分:实现角色表单对话框组件第五部分:全面测试总结前言 一个完善的权限系统…

Objective-c protocol 练习

题目描述&#xff1a; 请使用 Objective-C 中的 protocol 协议机制&#xff0c;实现一个简易的门禁控制系统。 系统包含两个类&#xff1a; AccessControlSystem —— 门禁系统&#xff0c;用于执行开门操作&#xff1b;Admin —— 实现权限判断逻辑的管理员。 要求如下&am…

科技创新赋能产业创新,双轮驱动助力新疆高质量发展!

在新疆维吾尔自治区成立70周年之际&#xff0c;中国产学研合作促进会于6月14日在乌鲁木齐举办“天山对话&#xff1a;推动新疆科技创新与产业创新”盛会。多位院士、专家、学者及企业代表齐聚一堂&#xff0c;探寻推动新疆科技创新和产业创新的新路径、新动能。活动现场&#x…

C#最佳实践:推荐使用 nameof 而非硬编码名称

C#最佳实践:推荐使用 nameof 而非硬编码名称 在 C# 编程领域,代码的可维护性、健壮性和可读性是衡量程序质量的重要指标。在日常开发中,我们常常会遇到需要引用类型、成员或变量名称的场景,比如在抛出异常时指定错误相关的变量名、在日志记录中标记关键元素名称等。传统的…

vue3 iframe 跨域-通讯

一、基础嵌套方法 直接在 HTML 中使用 <iframe> 标签指定 src 属性&#xff1a; <iframe src"https://目标网址.com" width"800" height"600"></iframe>‌限制‌&#xff1a;若目标网站设置了 X-Frame-Options 响应头&#x…

Iceberg与Hive集成深度

一、Iceberg在Hive中的ACID事务实现与实战 1.1 传统Hive的事务局限性 Hive原生仅支持非事务表&#xff08;Non-ACID&#xff09;&#xff0c;存在以下痛点&#xff1a; 不支持行级更新/删除并发写入时数据一致性无法保证无事务回滚机制历史版本查询需手动实现 1.2 Iceberg为…

深入剖析 Celery:分布式异步任务处理的利器

本文在创作过程中借助 AI 工具辅助资料整理与内容优化。图片来源网络。 文章目录 引言一、Celery 概述1.1 Celery 的定义和作用1.2 Celery 的应用场景 二、Celery 架构分析2.1 Celery 的整体架构2.2 消息中间件&#xff08;Broker&#xff09;2.3 任务队列&#xff08;Task Que…