简体   繁体   English

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

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

Background背景

I have developed a React app that uses Laravel as an API.我开发了一个使用 Laravel 作为 API 的 React 应用程序。 I have added logins via Passport and have been using the Personal Access Client approach quite successfully.我已经通过 Passport 添加了登录名,并且已经非常成功地使用了 Personal Access Client 方法。 I can add new users and tokens, I can revoke tokens, I can reset passwords... All API calls (except login and register) are guarded by the API middleware and it works.我可以添加新用户和令牌,我可以撤销令牌,我可以重置密码......所有 API 调用(登录和注册除外)都由 API 中间件保护,并且可以正常工作。 If I remove the Bearer ${token} from the header on any of these calls it returns 401 unauthenticated due to the ->middleware('auth:api') wrapper.如果我在任何这些调用中从 header 中删除Bearer ${token} ,由于 ->middleware('auth:api') 包装器,它会返回未经身份验证的 401。

The Problem问题

Everything works completely as expected... until I move everything to my Raspberry Pi server.一切都按预期工作......直到我将所有东西都移到我的 Raspberry Pi 服务器上。 As soon as I moved everything, the problem began.我一搬动所有东西,问题就开始了。 I can login and I can register, but as soon as I use the new bearer token (that I received from my login or register call(s)) on any of the endpoint calls that follow in my flow, it fails with 401 unauthenticated, immediately .我可以登录并且可以注册,但是一旦我在流程中的任何端点调用上使用新的不记名令牌(我从登录或注册调用中收到),它就会失败并出现 401 未经身份验证,马上 I ran the php artisan passport:client --personal command and successfully entered the id and secret into my.env file as usual.我运行了php artisan passport:client --personal命令,并像往常一样成功地将 id 和 secret 输入到 my.env 文件中。 I installed all the composer and vendor packages.我安装了所有的作曲家和供应商软件包。 I installed all passport package(s) and CLI commands.我安装了所有护照包和 CLI 命令。

It only fails on calls that use the auth middleware .它仅在使用 auth 中间件的调用上失败

I have done some digging and it seems the only change I can find (significantly) is that the Pi runs a 32 bit PHP where my localhost runs a 64 bit PHP.我做了一些挖掘,似乎我能找到的唯一变化(显着)是 Pi 运行 32 位 PHP,而我的 localhost 运行 64 位 PHP。 Other than that its the same code, DB, versions of Laravel and PHP, everything.除了相同的代码、DB、Laravel 和 PHP 的版本,一切。

I have tried using the command php artisan passport:client --personal --name="app-name" --redirect_uri="http://192.168.1.1/" which puts a record in the "oauth_clients" table but shows the redirect as http://localhost/ .我尝试使用命令php artisan passport:client --personal --name="app-name" --redirect_uri="http://192.168.1.1/"将记录放在“oauth_clients”表中,但显示重定向为http://localhost/ I then try to use SQL to change the value of the column named "redirect" to http://localhost/ , manually... but again the change does nothing.然后我尝试手动使用 SQL 将名为“redirect”的列的值更改为http://localhost/ ,但再次更改没有任何作用。 Calls still return 401 unauthenticated.呼叫仍然未经身份验证返回 401。

The only other things I can find that might be an issue are:我能找到的唯一可能是问题的其他事情是:

  1. The fact that all tokens in the database table "oauth_access_tokens", under the column called "redirect", are created with the redirect_uri of http://localhost .事实上,数据库表“oauth_access_tokens”中名为“redirect”的列下的所有令牌都是使用http://localhostredirect_uri创建的。 No matter what I do it's always localhost and not my servers domain or IP address (which is concerning).无论我做什么,它总是 localhost 而不是我的服务器域或 IP 地址(这是令人担忧的)。 Manually changing SQL as I said does nothing but I know Laravel uses a few "read-only" columns for auth so I wonder if this is one of them... perhaps personal access tokens only work on localhost?正如我所说,手动更改 SQL 什么也没做,但我知道 Laravel 使用一些“只读”列进行身份验证,所以我想知道这是否是其中之一......也许个人访问令牌仅适用于本地主机?
  2. My email_verified_at column in my "users" table (generated by passport commands) is null because I was not able to setup the "forgot my password" flow of Passport on localhost since emails won't send out on localhost.我的“用户”表(由护照命令生成)中的email_verified_at列是 null,因为我无法在本地主机上设置 Passport 的“忘记密码”流程,因为电子邮件不会在本地主机上发送。

What I have setup is this:我的设置是这样的:

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 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 AuthController Class

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

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

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

config/Auth.php配置/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 File .env 文件

Finally solved it!!终于解决了!!

Turns out it was Apache on the Raspberry Pi server blocking the Authorization header.原来是Raspberry Pi服务器上的 Apache 阻止了授权 header。 This finally unblocked me and solved my issues.这终于解除了我的障碍并解决了我的问题。

For anyone else coming from a Google search, you can go into your /etc/apache2/apache2.conf file and at the very bottom, paste:对于来自 Google 搜索的其他任何人,您可以将 go 放入您的/etc/apache2/apache2.conf文件并在最底部粘贴:

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

I am using a Raspberry Pi 4 with 32 bit PHP and Apache2.我正在使用具有 32 位 PHP 和 Apache2 的 Raspberry Pi 4。

Also, I didn't mention in my post that I have been using the following for my apache server root htaccess:另外,我在帖子中没有提到我一直在为我的 apache 服务器根 htaccess 使用以下内容:

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

.htaccess file, server root .htaccess 文件,服务器根目录

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM