Laravel 5.6 已签名 url 将无法在 APP_ENV=production 中使用
Laravel 5.6 signed url won't work in APP_ENV=production
我设置了两条路线
Route::get('/bugreport', 'SomeController@create')
->middleware('signed')
->name('bugreport');
Route::get('/getlink', function() {
return dd(\URL::signedRoute('bugreport', ['data' => 3]));
});
当 APP_ENV=local
我可以访问 /getlink
然后点击生成的 url 并显示它。当 APP_ENV=production
(更改变量时实际物理环境没有改变)这不再有效...说明无效签名。有什么建议么?
更新:
我们确实有...这可能是其中的一部分
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
if (!config('app.is_local')) {
URL::forceScheme('https');
}
}
注意:删除上面的代码实际上确实解决了这个问题,但随后它中断了,例如登录...所以要么需要了解原因,要么这不是一个选项:(。
更新更新:
环境是 heroku 并且 .htaccess 有(根据 https://help.heroku.com/J2R1S4T8/can-heroku-force-an-application-to-use-ssl-tls)
#### FORCE SSL
## see - https://help.heroku.com/J2R1S4T8/can-heroku-force-an-application-to-use-ssl-tls
RewriteCond %{HTTP_HOST} !=localhost
# If we receive a forwarded http request from a proxy...
RewriteCond %{HTTP:X-Forwarded-Proto} =http [OR]
# ...or just a plain old http request directly from the client
RewriteCond %{HTTP:X-Forwarded-Proto} =""
RewriteCond %{HTTPS} !=on
# Redirect to https version
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
### End Force SSL
更新:改为使用已接受的答案。
我最终将此归结为 Heroku 更改请求协议,这样即使客户端在 https
laravel 中发出请求,也始终会收到 http
在请求对象中。解决方法是
if (!config('app.is_local') && strpos($request->url(), 'http:') !== false)
{
$url = str_replace('http:', 'https:', $request->fullUrl());
$request = Request::create($url);
}
if (!$request->hasValidSignature()) {
return abort(403);
}
这足以满足我的需要。
我遇到了类似的问题 - 如果使用 TrustedProxy 中间件可以很容易地解决。
如果您在负载均衡器后面的 Heroku 或 AWS 上,并且您将 SSL 卸载到负载均衡器,您可能想要信任所有代理,以便 Laravel 的请求可以检测到您实际上是在一个 SSL 连接。
然后签名 URL 验证将起作用。
你可以在这里看到独库:
Laravel 5.7https://laravel.com/docs/5.7/requests#configuring-trusted-proxies
Laravel 5.6 https://laravel.com/docs/5.6/requests#configuring-trusted-proxies
我设置了两条路线
Route::get('/bugreport', 'SomeController@create')
->middleware('signed')
->name('bugreport');
Route::get('/getlink', function() {
return dd(\URL::signedRoute('bugreport', ['data' => 3]));
});
当 APP_ENV=local
我可以访问 /getlink
然后点击生成的 url 并显示它。当 APP_ENV=production
(更改变量时实际物理环境没有改变)这不再有效...说明无效签名。有什么建议么?
更新:
我们确实有...这可能是其中的一部分
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
if (!config('app.is_local')) {
URL::forceScheme('https');
}
}
注意:删除上面的代码实际上确实解决了这个问题,但随后它中断了,例如登录...所以要么需要了解原因,要么这不是一个选项:(。
更新更新:
环境是 heroku 并且 .htaccess 有(根据 https://help.heroku.com/J2R1S4T8/can-heroku-force-an-application-to-use-ssl-tls)
#### FORCE SSL
## see - https://help.heroku.com/J2R1S4T8/can-heroku-force-an-application-to-use-ssl-tls
RewriteCond %{HTTP_HOST} !=localhost
# If we receive a forwarded http request from a proxy...
RewriteCond %{HTTP:X-Forwarded-Proto} =http [OR]
# ...or just a plain old http request directly from the client
RewriteCond %{HTTP:X-Forwarded-Proto} =""
RewriteCond %{HTTPS} !=on
# Redirect to https version
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
### End Force SSL
更新:改为使用已接受的答案。
我最终将此归结为 Heroku 更改请求协议,这样即使客户端在 https
laravel 中发出请求,也始终会收到 http
在请求对象中。解决方法是
if (!config('app.is_local') && strpos($request->url(), 'http:') !== false)
{
$url = str_replace('http:', 'https:', $request->fullUrl());
$request = Request::create($url);
}
if (!$request->hasValidSignature()) {
return abort(403);
}
这足以满足我的需要。
我遇到了类似的问题 - 如果使用 TrustedProxy 中间件可以很容易地解决。
如果您在负载均衡器后面的 Heroku 或 AWS 上,并且您将 SSL 卸载到负载均衡器,您可能想要信任所有代理,以便 Laravel 的请求可以检测到您实际上是在一个 SSL 连接。 然后签名 URL 验证将起作用。
你可以在这里看到独库:
Laravel 5.7https://laravel.com/docs/5.7/requests#configuring-trusted-proxies
Laravel 5.6 https://laravel.com/docs/5.6/requests#configuring-trusted-proxies