使用Laravel Sanctum获取用户数据

21

之前我使用了Laravel的内置api令牌身份验证,但我想为不同的客户提供多个api令牌,并且在Laravel 7.x中,我尝试迁移到Laravel Sanctum。

API似乎可以正常验证用户,但当我尝试用 Auth::user(); 获取用户数据时,它返回null,而 Auth::guard('api')->user();也返回null。

我应该使用什么作为Auth guard?或者基于提供的令牌获取用户数据的方法是否正确?

非常感谢....


是否使用了自定义中间件进行身份验证?如果是,并且问题未得到解决,可以发布中间件的内容吗? - qwertynik
请使用@parsa-samandizadeh的解决方案,或者按照以下链接中描述的方式使用可选的 Sanctum Auth 中间件:https://laracasts.com/discuss/channels/laravel/laravel-sanctum-optional-auth-on-route?page=1&replyId=680807 - armezit
你是否在请求的头部Authorization字段之前加上了"Bearer "字符串和令牌? - ÄR Âmmãř Żąîñh
9个回答

37

auth('sanctum')->user()->id


auth('sanctum')->check()


没有中间件的情况下,您可以使用这些。

应该是最佳答案,正是所需之物,谢谢! - slothstronaut

27

首先,通过圣所认证中间件进行路由。

Route::get('/somepage', 'SomeController@MyMethod')->middleware('auth:sanctum');

然后,获取用户。

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class AuthController extends Controller
{
    public function MyMethod(Request $request) {
        return $request->user();
    }
}

auth()->user() 是一个全局帮助函数,Auth::user() 是一个支持门面模式,而 $request->user() 使用 http。你可以使用其中任何一个。

为了进行快速测试,请尝试:

Route::get('/test', function() {
    return auth()->user();
})->middleware('auth:sanctum');

请确保将您的令牌作为标题发送,例如:

Authorization: Bearer UserTokenHere

3
对于 API 请求,$request->user() 和 auth()->user() 返回 null。Auth::user() 也返回 null(似乎需要提供 guard)。 - she hates me
@shehatesme 你是否像上面那样在请求头中发送了令牌? - Gavin
@shehatesme 你需要使用 auth:sanctum 中间件,否则它会返回 null。 - Liga

3

最简单的方法是使用auth助手,例如:

$user =  auth('sanctum')->user();

或者您可以通过请求对象获取它

//SomeController.php
public function exampleMethod(Request $request)
{
   $user = $request->user();
}

通过 sanctum token 字符串获取用户,例如:

2|bTNlKViqCkCsOJOXWbtNASDKF7SyHwzHOPLNH

代码就像这样

use Laravel\Sanctum\PersonalAccessToken;
//...
$token = PersonalAccessToken::findToken($sactumToken);
$user = $token->tokenable;

注意:传递令牌的最常见方式是通过带有Bearer的授权头。


3

授权头

在 Authorization 标头中发送令牌,下面的代码将返回授权用户。

Route::middleware('auth:sanctum')->group(function () {
    Route::get('/profile/me', function (Request $request) {
        return $request->user();
    });
});

在Restful API中,建议您发送Accept标头以便在验证中间件中进行检查,如果未经过身份验证,则重定向。对于Restful API,默认情况下,如果用户未经过身份验证,则会将其重定向到登录表单(如果有的话)。

namespace App\Http\Middleware;

protected function redirectTo($request)
{
    if (!$request->expectsJson()) {
        return route('login');
    }
}

我对重定向没有任何问题,我只需要在控制器中获取Auth :: user()数据。 - she hates me
1
@shehatesme 请尝试使用 Auth::guard('sanctum')->user()。 - Aniket Muruskar

1
当您登录用户时,在您的登录函数中使用类似以下内容的代码。
public function login(Request $request)
{
    if(Auth::attempt($credentials))
    {
         $userid = auth()->user()->id;
    }
}

然后将此用户ID发送给客户端,并让其以安全的方式存储在客户端上。然后,每次请求时,您可以使用此用户ID为下一次请求提供数据。

0
 private $status_code= 200; // successfully

    public function register(Request $request)
    {
        // $validator = $this->validator($request->all())->validate();
        $validator = Validator::make($request->all(),
            [
                'name' => ['required', 'string', 'max:255'],
                'email' => ['required', 'string', 'email', 'max:255'], // , 'unique:users'
                'password' => ['required', 'string', 'min:4'],
            ]
        );
        if($validator->fails()) {
            return response()->json(["status" => "failed", "message" => "Please Input Valid Data", "errors" => $validator->errors()]);
        }
        $user_status = User::where("email", $request->email)->first();
        if(!is_null($user_status)) {
           return response()->json(["status" => "failed", "success" => false, "message" => "Whoops! email already registered"]);
        }

        $user = $this->create($request->all());
        if(!is_null($user)) {
            $this->guard()->login($user);
            return response()->json(["status" => $this->status_code, "success" => true, "message" => "Registration completed successfully", "data" => $user]);
        }else {
            return response()->json(["status" => "failed", "success" => false, "message" => "Failed to register"]);
        }
    }
    /**
     * Get a validator for an incoming registration request.
     *
     * @param  array  $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:4'],
        ]);
    }

    /**
     * Create a new user instance after a valid registration.
     * @author Mohammad Ali Abdullah .. 
     * @param  array  $data
     * @return \App\User
     */
    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);
    }
    protected function guard()
    {
        return Auth::guard();
    }
    /**
     * method public
    * @author Mohammad Ali Abdullah
    * @date 01-01-2021.
    */
    public function login(Request $request)
    {

        $validator = Validator::make($request->all(),
            [
                "email"             =>          "required|email",
                "password"          =>          "required"
            ]
        );
        // check validation email and password .. 
        if($validator->fails()) {
            return response()->json(["status" => "failed", "validation_error" => $validator->errors()]);
        }
        // check user email validation ..
        $email_status = User::where("email", $request->email)->first();
        if(!is_null($email_status)) {
            // check user password validation ..
            // ---- first try -----
            // $password_status    =   User::where("email", $request->email)->where("password", Hash::check($request->password))->first();
            // if password is correct ..
            // ---- first try -----
            // if(!is_null($password_status)) {
            if(Hash::check($request->password, $email_status->password)) {
                $credentials = $request->only('email', 'password');
                if (Auth::attempt($credentials)) {
                    // Authentication passed ..
                    $authuser = auth()->user();
                    return response()->json(["status" => $this->status_code, "success" => true, "message" => "You have logged in successfully", "data" => $authuser]);
                }
            }else {
                return response()->json(["status" => "failed", "success" => false, "message" => "Unable to login. Incorrect password."]);
            }
        }else{
            return response()->json(["status" => "failed", "success" => false, "message" => "Email doesnt exist."]);
        }
    }

    public function logout()
    {
        Auth::logout();
        return response()->json(['message' => 'Logged Out'], 200);
    }

0

我看到还没有被接受的答案。我刚遇到了我的 sanctum auth 无法工作的问题。auth() 助手始终返回 null。

为了解决这个问题,我在 api key 下的 kernel.php 中删除了注释。这是关于这个类的 \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class。这是因为默认情况下它被注释掉了。

'api' => [
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    'throttle:api',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

之后,我通过auth()助手访问了User对象。


-1
我曾经也遇到过同样的问题;我迁移到 Sanctum 后,惊讶地发现我的 $request->user() 为空。对我而言,解决方法是在堆栈中添加一些中间件来修改请求的 user() 解析器:
namespace App\Http\Middleware;

use Illuminate\Http\Request;

class PromoteSanctumUser
{
    /**
     * @param Request $request
     * @param \Closure $next
     */
    public function handle(Request $request, \Closure $next)
    {
        $sanctumUser = auth('sanctum')->user();

        if ($sanctumUser) {
            $request->setUserResolver(function() use ($sanctumUser) {
                return $sanctumUser;
            });
        }

        return $next($request);
    }
}

-1
请确保 Sanctum 中间件在 API 中。

1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接