You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 8 Sanctum自定义数据库生成认证Token问题求助

解决Laravel Sanctum对接遗留数据库的Token问题

核心疑问解答

  1. 是否可以基于自有表与自定义对象生成Token?
    完全可以。Sanctum不强制使用默认的users表和User模型,只要你的自定义模型继承Illuminate\Foundation\Auth\User(即Authenticatable),并引入Laravel\Sanctum\HasApiTokens trait,就能和Sanctum的Token系统兼容。

  2. 后端如何生成并返回Token?
    账号密码验证通过后,获取自定义用户模型的有效实例,调用createToken方法生成Token,返回plainTextToken给前端即可。示例代码:

// 假设自定义模型为LegacyUser
$user = LegacyUser::where('username', $request->username)->first();
// 替换为你遗留系统的密码校验逻辑
if ($user && password_verify($request->password, $user->password)) {
    $token = $user->createToken('web-access')->plainTextToken;
    return response()->json(['token' => $token]);
}
  1. 前端如何安全存储与获取Token?
  • 优先用HttpOnly Cookie:若前后端同域/子域,后端可将Token存入HttpOnly Cookie,前端无法通过JS访问,规避XSS风险。开启Sanctum的stateful配置并设置允许域名,请求时Cookie会自动携带。
  • LocalStorage/SessionStorage:跨域场景下可存在LocalStorage,但需注意XSS风险,建议配合CSRF防护。请求时在Authorization头携带Bearer {token}。

解决tokenable_id cannot be null错误

这个错误的本质是自定义模型的主键未被Sanctum正确识别,或调用createToken的模型实例无有效ID,按以下步骤排查:

  1. 正确配置自定义模型
    在LegacyUser模型中明确指定表名、主键及类型(若与默认自增int不同):
namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Laravel\Sanctum\HasApiTokens;

class LegacyUser extends Authenticatable
{
    use HasApiTokens;

    // 指定你的遗留用户表名
    protected $table = 'your_legacy_users_table';
    // 指定主键字段(比如不是默认的id,而是user_id)
    protected $primaryKey = 'user_id';
    // 主键非自增时设为false
    public $incrementing = false;
    // 主键为字符串时设为string
    protected $keyType = 'string';

    // 允许批量赋值的字段,按需调整
    protected $fillable = ['username', 'password'];
}
  1. 确保调用createToken的是有效实例
    必须使用从数据库查询出的、带有有效主键ID的模型实例,不能用new LegacyUser()创建空实例。

  2. 重写tokens关联(按需)
    若personal_access_tokens表的tokenable_id字段与模型主键不匹配,可重写模型的tokens方法:

public function tokens()
{
    return $this->morphMany(
        \Laravel\Sanctum\PersonalAccessToken::class,
        'tokenable',
        'tokenable_type',
        'tokenable_id' // 与personal_access_tokens表的外键字段名保持一致
    );
}

同时检查personal_access_tokens表的tokenable_id字段类型是否与用户主键类型匹配(比如用户主键是字符串,该字段也要设为varchar),不匹配则手动修改数据库表结构。


Laravel Passport替代方案

若Sanctum配置仍有问题,可尝试Passport,步骤如下:

  1. 配置自定义模型
    让LegacyUser继承Authenticatable并引入Laravel\Passport\HasApiTokens trait。

  2. 手动创建Passport所需表
    从Laravel Passport的迁移文件导出SQL语句,手动在遗留数据库中执行,创建oauth_clients、oauth_access_tokens等表。

  3. 配置Auth Guard
    修改config/auth.php,将api guard的驱动设为passport:

'guards' => [
    'api' => [
        'driver' => 'passport',
        'provider' => 'legacy_users', // 指定自定义用户provider
    ],
],

'providers' => [
    'legacy_users' => [
        'driver' => 'eloquent',
        'model' => App\Models\LegacyUser::class,
    ],
],
  1. 生成Token
    用密码授权模式生成Token,示例:
$user = LegacyUser::where('username', $request->username)->first();
if ($user && password_verify($request->password, $user->password)) {
    $token = $user->createToken('api-access')->accessToken;
    return response()->json(['token' => $token]);
}

内容的提问来源于stack exchange,提问作者Jorge Mauricio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 11:15:44