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

Laravel多Auth Guard+Sanctum在部分虚拟主机验证失败问题

问题:Laravel多Auth Guard结合Sanctum在特定虚拟主机上认证失败

我基于Laravel框架开发了一个使用多Auth Guard结合Sanctum的项目,本地环境运行完全正常。但上传至某虚拟主机后,登录流程可正常执行并返回token,尝试获取用户详情时却提示未认证。将项目上传至其他虚拟主机则可正常运行,请问该问题可能的原因是什么?

config/auth.php

<?php

return [

/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/

'defaults' => [
    'guard' => 'web',
    'passwords' => 'users',
],

/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session"
|
*/

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'memberGuard' => [
        'driver' => 'sanctum',
        'provider' => 'memberP',
    ],
    'adminGuard' => [
        'driver' => 'sanctum',
        'provider' => 'adminP',
    ]

],

/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\Models\User::class,
    ],
    'adminP' => [
        'driver' => 'eloquent',
        'model' => App\Models\User::class,
    ],
    'memberP' => [
        'driver' => 'eloquent',
        'model' => App\Models\Member::class,
    ],

    // 'users' => [
    //     'driver' => 'database',
    //     'table' => 'users',
    // ],
],

/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
|
| The expire time is the number of minutes that each reset token will be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
*/

'passwords' => [
    'users' => [
        'provider' => 'users',
        'table' => 'password_resets',
        'expire' => 60,
        'throttle' => 60,
    ],
    'adminGuard' => [
        'provider' => 'adminP',
        'table' => 'password_resets',
        'expire' => 60,
        'throttle' => 60,
    ],
    'memberGuard' => [
        'provider' => 'memberP',
        'table' => 'password_resets',
        'expire' => 60,
        'throttle' => 60,
    ],
],

/*
|--------------------------------------------------------------------------
| Password Confirmation Timeout
|--------------------------------------------------------------------------
|
| Here you may define the amount of seconds before a password confirmation
| times out and the user is prompted to re-enter their password via the
| confirmation screen. By default, the timeout lasts for three hours.
|
*/

'password_timeout' => 10800,

];

Auth/MemberController.php

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\Member;
use App\Models\User;
use App\Traits\ApiResponser;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;

class MemberController extends Controller
{
use ApiResponser;
/**
 * Create a new AuthController instance.
 *
 * @return void
 */
public function __construct()
{
    $this->middleware('auth:memberGuard', ['except' => ['login']]);
}

/**
 * Authenticate user and create token.
 *
 * @return token
 */
public function login(Request $request)
{
    Log::info('This is some useful information.');
    $fields = $request->validate([
        'accppa_member_id' => 'required',
        'password'  => 'required|string',
    ]);

    // Check user name
    $user = Member::where('accppa_member_id', $fields['accppa_member_id'])->first();

    // Check password
    if (!$user || !Hash::check($fields['password'], $user->password)) {
        return $this->error('Invalid Credentials', 401);
    }

    

    // Remove Existing tokens
    if ($user->tokens()->count() > 0) {
        $user->tokens()->delete();
    }

    $token = $user->createToken(uniqid());

    return $this->success([
        'token' => $token->plainTextToken
    ]);
}

/**
 * User
 *
 * @return void
 */
public function user()
{
    $user =  auth()->guard('memberGuard')->user();
    return response()->json($user);
}

 /**
 * Remove user token
 *
 * @return void
 */
public function logout(Request $request)
{
    
    $request->user()->currentAccessToken()->delete();

    return response()->json(['message' => 'Successfully logged out']);
}
}

可能的原因及排查方向

  • PHP版本或扩展不兼容:确认该虚拟主机的PHP版本与本地一致,Laravel和Sanctum有明确的版本依赖;同时检查是否安装了openssl、fileinfo等必需扩展,加密类扩展缺失会导致token验证失败。
  • 环境变量配置错误:检查主机上的.env文件,确保APP_KEY是有效的加密密钥(可通过php artisan key:generate重新生成),APP_URL与实际访问域名完全一致,SANCTUM_STATEFUL_DOMAINS包含当前主机域名。
  • 缓存未清理:上传后未刷新配置缓存,旧的认证配置仍在生效。执行以下命令清理缓存:
    php artisan config:clear
    php artisan cache:clear
    php artisan route:clear
    
  • 文件权限问题:Laravel的storage和bootstrap/cache目录权限不足,导致Sanctum无法读写token数据。将这些目录权限设置为755,所有者改为Web服务器运行用户(如apache、www-data)。
  • URL重写配置缺失:虚拟主机未正确配置Apache/Nginx的URL重写规则,导致请求无法到达Laravel入口文件,Sanctum无法解析Authorization头。
    • Apache:确保.htaccess文件存在且主机启用了mod_rewrite模块;
    • Nginx:配置文件中添加正确的try_files规则:
      location / {
          try_files $uri $uri/ /index.php?$query_string;
      }
      
  • 请求头被拦截:部分虚拟主机会拦截或修改Authorization请求头,导致token无法被Sanctum接收。可临时通过URL参数?token=你的令牌测试请求,若能正常认证,说明是请求头问题,联系主机服务商解决。
  • Sanctum配置问题:检查config/sanctum.php中的stateful数组,确保包含当前主机的域名,尤其是使用子域名的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 02:57:14