Laravel 10中Auth::user()输出用户密码的问题及安全需求
问题:Laravel 10中Auth::user()输出包含密码,如何避免敏感信息存入会话?
在Laravel 10项目中,执行print_r(Auth::user())时发现输出里包含了哈希后的用户密码,我不希望这类敏感信息以任何形式存储在会话中。
执行print_r(Auth::user())的输出结果:
stdClass Object ( [user] => App\Models\User Object ( [connection:protected] => mysql [table:protected] => users [primaryKey:protected] => id [keyType:protected] => int [incrementing] => 1 [with:protected] => Array ( ) [withCount:protected] => Array ( ) [preventsLazyLoading] => [perPage:protected] => 15 [exists] => 1 [wasRecentlyCreated] => [escapeWhenCastingToString:protected] => [attributes:protected] => Array ( [id] => 14 [username] => ndmblgc [email] => ******@gmail.com [email_verified_at] => [password] => $2y$10$yrZgaQbRjPVV47FXxZp7pezDEgz9KoY7vRhCLo4aJDE/xqtTy05.. [remember_token] => c09Sw0dKHneYTqyrCqZtXIyf66qYIS7zeCTlsItQRSwccP6SKHmGACZf968a [email_valid] => 0 [created_at] => 2023-11-11 19:02:24 [updated_at] => 2023-11-11 19:02:24 ) [original:protected] => Array ( [id] => 14 [username] => ndmblgc [email] => ******@gmail.com [email_verified_at] => [password] => $2y$10$yrZgaQbRjPVV47FXxZp7pezDEgz9KoY7vRhCLo4aJDE/xqtTy05.. [remember_token] => c09Sw0dKHneYTqyrCqZtXIyf66qYIS7zeCTlsItQRSwccP6SKHmGACZf968a [email_valid] => 0 [created_at] => 2023-11-11 19:02:24 [updated_at] => 2023-11-11 19:02:24 ) [changes:protected] => Array ( ) [casts:protected] => Array ( [email_verified_at] => datetime [password] => hashed ) [classCastCache:protected] => Array ( ) [attributeCastCache:protected] => Array ( ) [dateFormat:protected] => [appends:protected] => Array ( ) [dispatchesEvents:protected] => Array ( ) [observables:protected] => Array ( ) [relations:protected] => Array ( ) [touches:protected] => Array ( ) [timestamps] => 1 [usesUniqueIds] => [hidden:protected] => Array ( [0] => password [1] => remember_token ) [visible:protected] => Array ( ) [fillable:protected] => Array ( [0] => username [1] => email [2] => email_verified_at [3] => remember_token [4] => email_valid ) [guarded:protected] => Array ( [0] => * ) [rememberTokenName:protected] => remember_token [accessToken:protected] => ) )
User模型代码:
namespace App\Models; // use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Sanctum\HasApiTokens; class User extends Authenticatable { use HasApiTokens, HasFactory, Notifiable; /** * The attributes that are mass assignable. * * @var array<int, string> */ protected $fillable = [ 'username', 'email', 'email_verified_at', 'remember_token', 'email_valid', ]; /** * The attributes that should be hidden for serialization. * * @var array<int, string> */ protected $hidden = [ 'password', 'remember_token', ]; /** * The attributes that should be cast. * * @var array<string, string> */ protected $casts = [ 'email_verified_at' => 'datetime', 'password' => 'hashed', ]; }
登录函数代码:
$username = $request->post('username'); $password = ($request->post('password')); $login = Auth::attempt([ 'username' => $username, 'password' => $password ]); if($login){ $user = Auth::user(); return redirect('home'); }else{ return redirect(route('login'))->with('login_fail_1',"Kullanıcı adı yada parola hatalı."); }
解决方案说明:
1. 先明确:会话中并未存储完整用户对象
Laravel的Auth系统默认仅在会话中存储用户ID,而非整个用户数据。每次调用Auth::user()时,框架都会通过会话里的ID重新从数据库查询用户信息,你看到的密码是数据库查询结果的一部分,并非存储在会话中。可以执行dd(session()->all())验证,会话里只会有类似login_web_xxxx的键,对应值是用户ID。
2. 如何避免查询用户时加载密码字段
如果你想彻底避免查询用户时获取密码(即使是哈希后的),可以通过以下两种方式实现:
方式一:登录后手动替换认证用户对象
在登录逻辑中,查询用户时只选择需要的字段,再设置为认证用户:
if($login){ // 仅查询需要的字段,排除password $user = \App\Models\User::select([ 'id', 'username', 'email', 'email_verified_at', 'email_valid', 'created_at', 'updated_at' ])->find(Auth::id()); Auth::setUser($user); return redirect('home'); }
方式二:给User模型添加全局查询作用域
在User模型中添加全局作用域,默认查询时自动排除密码字段:
namespace App\Models; // 省略其他引入代码 use Illuminate\Database\Eloquent\Builder; class User extends Authenticatable { use HasApiTokens, HasFactory, Notifiable; // 省略现有属性... protected static function boot() { parent::boot(); // 添加全局作用域,默认查询排除password static::addGlobalScope('withoutPassword', function (Builder $query) { $query->select([ 'id', 'username', 'email', 'email_verified_at', 'remember_token', 'email_valid', 'created_at', 'updated_at' ]); }); } // 省略其他方法... }
注意:如果后续有需要获取密码的场景(比如修改密码验证),需要临时移除该作用域:
$user = \App\Models\User::withoutGlobalScope('withoutPassword')->find($userId);
3. 关于$hidden属性的作用
你在模型中定义的$hidden属性是正常生效的,它的作用是在序列化用户对象时(比如返回JSON响应、转成数组)自动隐藏指定字段。例如执行return response()->json(Auth::user())时,密码和remember_token不会出现在响应里,这是符合预期的。
内容的提问来源于stack exchange,提问作者Mehmet Nedim Bilgiç
相关产品推荐
相关产品推荐

