Laravel 5.7 签名路由返回 403 无效签名

Lar*_*Dev 6 php url signature laravel

我正在尝试利用 Laravel 5.7 中新的签名中间件,但由于某种原因,生成的签名 URL 返回 403 无效签名。

我使用的是最新的 Laravel 版本,PHP 7.2

这是我的 web.php 路由:

Route::get('/report/{user}/{client}', function ($user, $client) {
    return ("El usuario es: $user y el cliente es: $client");
})->name('report.client')->middleware('signed');
Run Code Online (Sandbox Code Playgroud)

这是在我的控制器中:

$objDemo->tempURL = Url::temporarySignedRoute('report.client', now('America/Panama')->addDays(5), [
            'user' => 1,
            'client' => 1
        ]);
Run Code Online (Sandbox Code Playgroud)

生成 URL 并显示如下内容:

https://example.com/report/1/1?expires=1545440368&signature=55ad67fa049a74fe8e123c664e50f53564b76154e2dd805c5927125f63c390a1

但是当我单击链接时,结果是 403 消息:“签名无效”

有任何想法吗?提前致谢

- - - - - -更新 - - - - - -

我已经做过的事情:

  1. 无需签名即可尝试路线,并且完美运行
  2. 试试不带参数只签名的路由
  3. 尝试没有临时设置和只签名的路线
  4. 将 cloudflare 的 ip 设置为受信任的代理
  5. 禁用HTTPS,启用HTTPS

似乎没有任何效果,总是得到 403 无效签名页

-----------更新 2------------

好的,经过一些挖掘和测试,我发现如果用户登录,laravel 签名的路由将不起作用,这很奇怪,如果我注销,则该路由完美运行,但如果我登录,则它显示403错误,这可能是因为Laravel在其他一切之后添加了会话cookie标头?所以签名的路由因此而失败?应该是这样吗?

奇怪,因为假设我想为我的用户创建一个临时链接来下载某些东西,如果他们登录到我的 Laravel 应用程序,他们将收到此 403 错误消息... :(

------------更新 3------------

我尝试全新安装 Laravel 并且运行良好,所以它来自我的主要 Laravel 应用程序,还尝试将每个 composer 依赖项安装到 Laravel 的全新安装中,无论用户登录状态如何,它仍然可以完美运行,所以它不是一个与我的依赖项冲突。

Lar*_*Dev 9

在调试 UrlGenerator::hasValidSignature() 之后,我以 DD 结束了里面的变量,UrlGenerator.php如下所示:

public function hasValidSignature(Request $request, $absolute = true)
    {
        $url = $absolute ? $request->url() : '/'.$request->path();

        //dd($url);

        $original = rtrim($url.'?'.Arr::query(
            Arr::except($request->query(), 'signature')
        ), '?');

        dd($original);
        $expires = Arr::get($request->query(), 'expires');

        $signature = hash_hmac('sha256', $original, call_user_func($this->keyResolver));

        return  hash_equals($signature, (string) $request->query('signature', '')) &&
               ! ($expires && Carbon::now()->getTimestamp() > $expires);
    }
Run Code Online (Sandbox Code Playgroud)

$original变量向我展示了我的 URL 实际发生了什么,并显示了以下内容:

https://example.com/report/1/1?expires=1546586977&settings%5Bincrementing%5D=1&settings%5Bexists%5D=1&settings%5BwasRecentlyCreated%5D=0&settings%5Btimestamps%5D=1&profile%5Bincrementing%5D=1&profile%5Bexists%5D=1&profile%5BwasRecentlyCreated%5D=0&profile%5Btimestamps%5D=1&user%5Bincrementing%5D=1&user%5Bexists%5D=1&user%5BwasRecentlyCreated%5D=0&user%5Btimestamps%5D=1
Run Code Online (Sandbox Code Playgroud)

如您所见,在 expires 参数之后有参数,在路由创建之后添加了那些参数,这就是问题所在,发生这种情况是因为我有一个中间件向视图共享一些信息,如下所示:

UserDataMiddleware.php

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\Auth;
use App\User;
use App\Setting;
use App\UserProfile;
use Illuminate\Support\Facades\View;

class UserData
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {

        if (Auth::check()) {
            $settings = Setting::where('user_id', Auth::user()->id)->first();
            $profile = UserProfile::where('user_id', Auth::id())->first();
            $user = Auth::user();

            View::share('settings', $settings); //Another way to share variables, with the View::share
            View::share('profile', $profile);

            //Now we need to share owr variables trough the REQUEST to our controllers
            $request->merge([
                'settings' => $settings,
                'profile' => $profile,
                'user' => $user
            ]);


        }
        return $next($request);
    }
}
Run Code Online (Sandbox Code Playgroud)

这个中间件在中间件​​组内,所以如果将来有人对此进行实验,那么这就是问题所在,然后它可以先检查一下。

  • 我知道这已经发布很久了,但这救了我的命。我从来没有想到过这一点,所以谢谢你! (4认同)

小智 5

试试下面的代码:

class TrustProxies extends Middleware
{
    protected $proxies = '*';
    protected $headers = Request::HEADER_X_FORWARDED_ALL;
}
Run Code Online (Sandbox Code Playgroud)

  • @developer_avijit - 也许尝试将您的评论作为答案的一部分? (2认同)