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

Lumen使用Tymon JWT库,通过非账号密码字段验证生成令牌

用Tymon JWT实现自定义字段(ID/Mobile/OTP)验证并生成令牌

没问题,我来帮你实现这个需求——跳过默认的邮箱密码验证,用id、mobile和otp三个字段匹配用户后,通过Tymon JWT库生成有效令牌。以下是具体实现步骤:

1. 确保User模型实现JWTSubject接口

Tymon JWT需要从用户模型获取唯一标识和自定义声明,所以你的User模型必须实现JWTSubject接口:

namespace App\Models;

use Illuminate\Foundation\Auth\User as Authenticatable;
use Tymon\JWTAuth\Contracts\JWTSubject;

class User extends Authenticatable implements JWTSubject
{
    // 你的模型属性、关联等代码...

    // 返回用户唯一标识(通常是主键ID)
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    // 返回自定义JWT声明(可以添加你需要的字段,比如mobile)
    public function getJWTCustomClaims()
    {
        return [
            'mobile' => $this->mobile,
            'user_id' => $this->id
        ];
    }
}

2. 编写自定义登录验证逻辑

创建一个控制器方法,处理前端传来的id、mobile、otp参数,验证匹配后生成令牌:

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Tymon\JWTAuth\Facades\JWTAuth;
use Illuminate\Support\Facades\Validator;

class OtpLoginController extends Controller
{
    public function authenticate(Request $request)
    {
        // 第一步:验证请求参数的合法性
        $validator = Validator::make($request->all(), [
            'id' => 'required|integer',
            'mobile' => 'required|string',
            'otp' => 'required|string',
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 400);
        }

        // 第二步:查询匹配的用户记录
        $user = User::where([
            'id' => $request->id,
            'mobile' => $request->mobile,
            'otp' => $request->otp,
        ])->first();

        // 如果没有找到匹配用户,返回认证失败
        if (!$user) {
            return response()->json(['error' => 'Invalid credentials'], 401);
        }

        // 第三步:生成JWT令牌(可以额外添加自定义声明)
        $token = JWTAuth::fromUser($user, [
            'additional_claim' => 'your_custom_value' // 可选:添加更多自定义字段
        ]);

        // 第四步:返回令牌及相关信息
        return response()->json([
            'access_token' => $token,
            'token_type' => 'bearer',
            'expires_in' => auth()->factory()->getTTL() * 60, // 令牌过期时间(秒)
            'user' => $user->only(['id', 'mobile']) // 返回需要的用户信息
        ]);
    }
}

3. (可选)配置自定义认证守卫

如果想让逻辑更规范,可以在config/auth.php中配置一个自定义的JWT守卫:

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],

    // 添加自定义守卫
    'otp-api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],

之后在控制器中可以用这个守卫来生成令牌,效果和JWTAuth::fromUser()一致:

$token = auth('otp-api')->login($user);

4. 安全建议

  • 验证成功后立即失效当前OTP:比如更新用户表的otp字段为null,或者添加otp_expired_at字段标记过期时间,避免OTP被重复使用。
  • 限制OTP的有效时间:在生成OTP时就设置过期时间,查询时同时验证otp_expired_at > now()。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:59:55