Laravel 5.6+Passport移动端API认证:注册登录及密钥存储问题
基于Laravel 5.6实现移动端用户注册、登录与持久化API授权
嘿,针对你提出的Laravel 5.6移动端授权需求,我来一步步帮你落地实现——核心用Laravel Passport来搞定资源所有者凭证授权,同时解决client_secret的安全问题,还要满足"手动退出前保持登录"的要求。
一、先搭好Passport基础环境
Laravel 5.6官方推荐用Passport实现OAuth2授权,正好支持你需要的资源所有者凭证(密码授权)模式。
- 安装对应版本的Passport:
composer require laravel/passport:^7.0
(Laravel 5.6适配Passport 7.x,别装错版本哦)
- 执行迁移生成Passport需要的数据库表:
php artisan migrate
- 生成加密密钥和OAuth客户端:
php artisan passport:install
这一步会输出两个客户端信息,重点记好Password Grant Client的client_id和client_secret,后面配置要用。
- 给
User模型添加Passport的Trait:
use Laravel\Passport\HasApiTokens; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable { use HasApiTokens, Notifiable; // 原有的模型代码... }
- 配置Passport路由和令牌有效期:
在app/Providers/AuthServiceProvider.php的boot方法里添加:
use Laravel\Passport\Passport; public function boot() { $this->registerPolicies(); Passport::routes(); // 把令牌有效期拉满(比如10年),满足"手动退出前保持授权"的需求 Passport::tokensExpireIn(now()->addYears(10)); Passport::refreshTokensExpireIn(now()->addYears(10)); }
- 修改
config/auth.php,把API guard的驱动改成passport:
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'passport', 'provider' => 'users', ], ],
二、实现用户注册API
先搞个注册接口,让移动端能创建用户账号:
- 创建
app/Http/Controllers/Api/RegisterController.php:
namespace App\Http\Controllers\Api; use App\User; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Hash; class RegisterController extends Controller { public function register(Request $request) { // 验证请求参数 $request->validate([ 'name' => 'required|string|max:255', 'email' => 'required|string|email|max:255|unique:users', 'password' => 'required|string|min:6|confirmed', ]); // 创建用户 $user = User::create([ 'name' => $request->name, 'email' => $request->email, 'password' => Hash::make($request->password), ]); // 注册成功直接生成令牌,让用户自动登录 $token = $user->createToken('MobileApp')->accessToken; return response()->json([ 'access_token' => $token, 'token_type' => 'Bearer', 'user' => $user ], 201); } }
- 在
routes/api.php里注册路由:
Route::post('register', 'Api\RegisterController@register');
三、解决client_secret的安全问题
你担心的移动端存储client_secret风险确实存在,这里给你两种靠谱的解决方案:
方案1:后端封装密码授权请求(推荐)
让移动端只传用户名和密码,后端内部带上client_id和client_secret去请求令牌,完全避免客户端暴露敏感信息:
- 创建
app/Http/Controllers/Api/LoginController.php:
namespace App\Http\Controllers\Api; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Http; class LoginController extends Controller { public function login(Request $request) { $request->validate([ 'email' => 'required|email', 'password' => 'required', ]); // 后端内部调用Passport的密码授权端点 $response = Http::asForm()->post(config('app.url').'/oauth/token', [ 'grant_type' => 'password', 'client_id' => env('PASSPORT_PASSWORD_CLIENT_ID'), 'client_secret' => env('PASSPORT_PASSWORD_CLIENT_SECRET'), 'username' => $request->email, 'password' => $request->password, 'scope' => '', ]); if ($response->status() !== 200) { return response()->json(['message' => '登录失败,用户名或密码错误'], 401); } return response()->json($response->json()); } }
- 在
.env文件里配置之前拿到的密码客户端信息:
PASSPORT_PASSWORD_CLIENT_ID=2 # 替换成你实际的client_id PASSPORT_PASSWORD_CLIENT_SECRET=xxxxxx # 替换成你实际的client_secret
- 注册登录路由到
routes/api.php:
Route::post('login', 'Api\LoginController@login');
方案2:用个人访问令牌(更简单)
如果不需要严格的OAuth2客户端验证,直接给用户生成个人访问令牌,全程不用管client_secret:
修改LoginController的login方法:
public function login(Request $request) { $request->validate([ 'email' => 'required|email', 'password' => 'required', ]); // 验证用户名密码 if (!auth()->attempt($request->only('email', 'password'))) { return response()->json(['message' => '登录失败'], 401); } // 生成永久有效的令牌 $user = auth()->user(); $token = $user->createToken('MobileApp')->accessToken; return response()->json([ 'access_token' => $token, 'token_type' => 'Bearer', 'user' => $user ]); }
四、实现手动退出功能
要让用户能主动退出,就需要撤销当前的访问令牌:
- 创建
app/Http/Controllers/Api/LogoutController.php:
namespace App\Http\Controllers\Api; use Illuminate\Http\Request; use App\Http\Controllers\Controller; class LogoutController extends Controller { public function logout(Request $request) { // 撤销当前请求对应的令牌 $request->user()->token()->revoke(); return response()->json(['message' => '已成功退出登录']); } }
- 注册需要授权的退出路由到
routes/api.php:
Route::middleware('auth:api')->post('logout', 'Api\LogoutController@logout');
五、移动端请求示例
- 登录请求:
POST /api/login Content-Type: application/json { "email": "user@example.com", "password": "password123" }
- 返回示例:
{ "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6Ij...", "token_type": "Bearer", "expires_in": 315360000, "user": { "id": 1, "name": "Test User", "email": "user@example.com" } }
- 后续API请求要在请求头带上令牌:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6Ij...
内容的提问来源于stack exchange,提问作者Varin
相关产品推荐
相关产品推荐

