以下是一個基于 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"
}
安全增強建議
-
HTTPS 強制使用:
// config/web.php 'components' => ['request' => ['cookieValidationKey' => 'your-key','enableCsrfValidation' => false, // API 通常禁用 CSRF'parsers' => ['application/json' => 'yii\web\JsonParser',],], ],
-
速率限制:
// 在控制器中添加 use yii\filters\RateLimiter;public function behaviors() {$behaviors = parent::behaviors();$behaviors['rateLimiter'] = ['class' => RateLimiter::class,];return $behaviors; }
-
刷新令牌機制:
- 實現雙令牌系統(access token + refresh token)
- access token 設置較短有效期(如 30 分鐘)
- 使用 refresh token 獲取新 access token
-
敏感操作日志:
- 記錄所有關鍵操作(登錄、數據修改等)
- 包含用戶 ID、IP 地址和時間戳
這個框架提供了完整的 JWT 認證實現,包含了用戶管理、Token 生成與驗證、API 保護等核心功能,可以直接作為基礎進行擴展開發。
通義千問-回答
實操成功