模仿Apache';用PHP实现ProxyPassReverse 问题摘要
假设您运行一台服务器,并且希望仅为使用用户名和密码登录的用户(经过身份验证的用户)提供本地主机应用程序中的内容 该应用程序在您的服务器上运行,但不向公众公开。它仅在您的服务器上通过提供 为简单起见,假设您是这样运行localhost应用程序的:模仿Apache';用PHP实现ProxyPassReverse 问题摘要,php,laravel,authentication,proxy,Php,Laravel,Authentication,Proxy,假设您运行一台服务器,并且希望仅为使用用户名和密码登录的用户(经过身份验证的用户)提供本地主机应用程序中的内容 该应用程序在您的服务器上运行,但不向公众公开。它仅在您的服务器上通过提供 为简单起见,假设您是这样运行localhost应用程序的: cd my-private-folder python3 -m http.server 3838 经过身份验证的用户应该能够转到以查看 本地主机应用程序提供的内容 未经验证的用户应被拒绝访问并重定向到登录页面 问题 Apache有一个指令ProxyP
cd my-private-folder
python3 -m http.server 3838
经过身份验证的用户应该能够转到以查看
本地主机应用程序提供的内容
未经验证的用户应被拒绝访问并重定向到登录页面
问题
- Apache有一个指令
,它在请求发送到目标之前修改请求中的HTTP头。它还有一个指令ProxyPass
,在返回用户之前修改响应中的标题ProxyPassReverse
- 有没有办法在PHP中模仿Apache的行为
- 有没有一种简单的方法可以在PHP框架中实现这一点
尝试1失败:正在使用路由 以下是我在Laravel 5.5上的尝试:
# /var/www/example.com/routes/web.php
Route::get('/app', function() {
return Response::make(
file_get_contents("http://localhost:3838/")
);
});
# This does not work, because the HTTP header is not modified.
Route::get('/app/{any}', function($any) {
return Response::make(
file_get_contents("http://localhost:3838/$any")
);
})->where('any', '.*');
这将成功地将内容从localhost:3838
传递到example.com/app
,但由于未修改HTTP头,因此无法传递应用程序请求的任何资源
例如:
- localhost应用程序使用Javascript请求
/resource.jpg
- 我希望资源从传递到
- 相反,应用程序发出一个失败的请求以获取
使用Apache Apache工作得很好!但是,添加新用户需要在服务器上运行
htpasswd
命令
有了Laravel,新用户应该能够自己在网站上注册
如果没有Laravel,您可以使用Apache保护应用程序,如下所示:
# /etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>
ServerName example.com
Redirect /app /app/
ProxyPass /app/ http://localhost:3838/
ProxyPassReverse /app/ http://localhost:3838/
ProxyPreserveHost On
<Location /app/>
AuthType Basic
AuthName "Restricted Access - Please Authenticate"
AuthUserFile /etc/httpd/htpasswd.users
Require user myusername
# To add a new user: htpasswd /etc/httpd/htpasswd.users newuser
</Location>
</VirtualHost>
#/etc/apache2/sites available/example.com.conf
ServerName example.com
重定向/app/app/
ProxyPass/应用程序/http://localhost:3838/
ProxyPassReverse/应用程序/http://localhost:3838/
代理主机
AuthType Basic
AuthName“受限访问-请验证”
AuthUserFile/etc/httpd/htpasswd.users
需要用户myusername
#添加新用户的步骤:htpasswd/etc/httpd/htpasswd.users newuser
这个相关的回答帮助我更好地理解了ProxyPassReverse
指令的工作原理:
localhost:3838
应用程序:
# /var/www/example.com/routes/web.php
Route::get('/app/{any}', function($any) {
return Response::make(
file_get_contents("http://localhost:3838/$any")
);
})->where('any', '.*');
Route::get('/{assets}', function($assets) {
return Response::make(
file_get_contents("http://localhost:3838/$assets")
);
})->where('assets', '.*(png|jpe?g|js)');
我认为Jens Segers有一个软件包,可以让PHP模拟
ProxyPass
指令:
下面是GitHub自述文件中的一个示例:
use Proxy\Proxy;
use Proxy\Adapter\Guzzle\GuzzleAdapter;
use Proxy\Filter\RemoveEncodingFilter;
use Zend\Diactoros\ServerRequestFactory;
// Create a PSR7 request based on the current browser request.
$request = ServerRequestFactory::fromGlobals();
// Create a guzzle client
$guzzle = new GuzzleHttp\Client();
// Create the proxy instance
$proxy = new Proxy(new GuzzleAdapter($guzzle));
// Add a response filter that removes the encoding headers.
$proxy->filter(new RemoveEncodingFilter());
// Forward the request and get the response.
$response = $proxy->forward($request)->to('http://example.com');
// Output response to the browser.
(new Zend\Diactoros\Response\SapiEmitter)->emit($response);
你能澄清你所说的“Laravel不重写URL…”是什么意思吗?如果在
/app/{any}
路径内输出dd(“http://localhost:3838/$any”)代码>你看到了什么?在/app/{any}
路线中,我添加了dd(“http://localhost:3838/$any”)代码>。当我访问http://example.com/app/shared
我明白了“http://localhost:3838/shared“
只是澄清一下,localhost:3838
已经开发好了,您正试图在Laravel中制作一个代理?@Diogo是的,没错。@DiogoSgrillo这只是问题的一个症状。应用程序(localhost:3838
)认为请求路径是localhost:3838
,因此它返回该路径下的资产(例如:localhost:3838/resource.jpg
),当它需要将它们作为localhost:3838/app/resource.jpg
返回时,应用程序需要知道它正在/app
下运行。对不起,但这不行。经过更多的研究,我意识到我正试图模仿Apache指令ProxyPass
和ProxyPassReverse
的行为。这些指令在HTTP头到达localhost
app之前修改它。当localhost
应用程序响应时,将再次修改标题,然后再将其发送回用户浏览器。因此,PHP还必须修改HTTP头以获得与Apache相同的行为。file\u get\u contents
函数只是一个hack,但它不会修改标题。