簡體   English   中英

Laravel API 端點“401 Unauthorized”在服務器上但在 Localhost 上工作正常

[英]Laravel API Endpoint "401 Unauthorized" on Server But Works Fine On Localhost

背景

我開發了一個使用 Laravel 作為 API 的 React 應用程序。 我已經通過 Passport 添加了登錄名,並且已經非常成功地使用了 Personal Access Client 方法。 我可以添加新用戶和令牌,我可以撤銷令牌,我可以重置密碼......所有 API 調用(登錄和注冊除外)都由 API 中間件保護,並且可以正常工作。 如果我在任何這些調用中從 header 中刪除Bearer ${token} ,由於 ->middleware('auth:api') 包裝器,它會返回未經身份驗證的 401。

問題

一切都按預期工作......直到我將所有東西都移到我的 Raspberry Pi 服務器上。 我一搬動所有東西,問題就開始了。 我可以登錄並且可以注冊,但是一旦我在流程中的任何端點調用上使用新的不記名令牌(我從登錄或注冊調用中收到),它就會失敗並出現 401 未經身份驗證,馬上 我運行了php artisan passport:client --personal命令,並像往常一樣成功地將 id 和 secret 輸入到 my.env 文件中。 我安裝了所有的作曲家和供應商軟件包。 我安裝了所有護照包和 CLI 命令。

它僅在使用 auth 中間件的調用上失敗

我做了一些挖掘,似乎我能找到的唯一變化(顯着)是 Pi 運行 32 位 PHP,而我的 localhost 運行 64 位 PHP。 除了相同的代碼、DB、Laravel 和 PHP 的版本,一切。

我嘗試使用命令php artisan passport:client --personal --name="app-name" --redirect_uri="http://192.168.1.1/"將記錄放在“oauth_clients”表中,但顯示重定向為http://localhost/ 然后我嘗試手動使用 SQL 將名為“redirect”的列的值更改為http://localhost/ ,但再次更改沒有任何作用。 呼叫仍然未經身份驗證返回 401。

我能找到的唯一可能是問題的其他事情是:

  1. 事實上,數據庫表“oauth_access_tokens”中名為“redirect”的列下的所有令牌都是使用http://localhostredirect_uri創建的。 無論我做什么,它總是 localhost 而不是我的服務器域或 IP 地址(這是令人擔憂的)。 正如我所說,手動更改 SQL 什么也沒做,但我知道 Laravel 使用一些“只讀”列進行身份驗證,所以我想知道這是否是其中之一......也許個人訪問令牌僅適用於本地主機?
  2. 我的“用戶”表(由護照命令生成)中的email_verified_at列是 null,因為我無法在本地主機上設置 Passport 的“忘記密碼”流程,因為電子郵件不會在本地主機上發送。

我的設置是這樣的:

public function boot()
{
    $this->registerPolicies();

    Passport::pruneRevokedTokens();
    Passport::tokensExpireIn(Carbon::now()->addDays(1));
    Passport::refreshTokensExpireIn(Carbon::now()->addDays(14));
    Passport::personalAccessTokensExpireIn(Carbon::now()->addDays(1));
}

AuthServiceProvider Class

public function register(Request $request) {
    $validatedData = $request->validate([
        'image_url' => 'required',
        'last_name' => 'required|max:55',
        'image_url' => 'required|max:250',
        'first_name' => 'required|max:55',
        'password' => 'required|confirmed',
        'email' => 'email|required|unique:users',
    ]);

    $validatedData['password'] = bcrypt($request->password);


    if ($request->hasFile('image_url')) {
        $imageFile = $request->file('image_url');
        $imageExtension = $imageFile->extension();

        if (strtolower($imageExtension) === 'png' || strtolower($imageExtension) === 'jpg') {
            $validatedData['image_url'] = Storage::url( $request->file('image_url')->store('user_pics', 'public') );
        }
    
        $user = User::create($validatedData);
        
        date_default_timezone_set('UTC');
        $date = new \DateTime( date('Y-m-d H:i:s') );
        $user->email_verified_at = $date->format('c');

        $accessToken = $user->createToken('authToken-'.$user->id, ['*'])->accessToken;

        return response([ 'user' => $user, 'access_token' => $accessToken ]);

    } else {
        abort(404, 'Cannot register user without a user image!');
    }
}


public function login(Request $request) {
    $loginData = $request->validate([
        'email' => 'email|required',
        'password' => 'required'
    ]);

    if (!auth()->attempt($loginData)) {
        return response()->json(['statusText' => 'Unauthorized'], 401);
    }

    $user = auth()->user();
    $accessToken = auth()->user()->createToken('authToken-'.$user->id, ['*'])->accessToken;

    return response([ 'user' => $user, 'access_token' => $accessToken ]);
}


public function logout(Request $request) {
    if (auth()->guard('api')->check()) {
        auth()->guard('api')->user()->OauthAcessToken()->delete();

        return response()->json([ 'msg' => 'Successfully logged out!' ]);
    
    } else {
        return abort(404, 'Must be logged in to log a user out');
    }
}


public function refreshToken(Request $request) {
    if (auth()->guard('api')->check()) {
        $user = auth()->user();
        $accessToken = auth()->user()->createToken('authToken-'.$user->id, ['*'])->accessToken;

        return response([ 'user' => $user, 'access_token' => $accessToken ]);
    
    } else {
        return abort(404, 'Must be logged in to refresh a token!');
    }
}

AuthController Class

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

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

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

配置/Auth.php

APP_NAME=MyName
APP_ENV=dev
APP_DEBUG=true
APP_URL=http://192.168.1.1
PASSPORT_PERSONAL_ACCESS_CLIENT_ID="1"
PASSPORT_PERSONAL_ACCESS_CLIENT_SECRET="[SOME LONG HASH]"

.env 文件

終於解決了!!

原來是Raspberry Pi服務器上的 Apache 阻止了授權 header。 這終於解除了我的障礙並解決了我的問題。

對於來自 Google 搜索的其他任何人,您可以將 go 放入您的/etc/apache2/apache2.conf文件並在最底部粘貼:

SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

我正在使用具有 32 位 PHP 和 Apache2 的 Raspberry Pi 4。

另外,我在帖子中沒有提到我一直在為我的 apache 服務器根 htaccess 使用以下內容:

# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

.htaccess 文件,服務器根目錄

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM