假设您运行服务器并希望仅为已使用用户名和密码登录的用户(经过身份验证的用户)提供localhost应用程序中的内容。
该应用在您的服务器上运行,但不向公众公开。它只能通过您服务器上的http://localhost:3838获得。
为简单起见,假设您运行localhost应用程序的方式如下:
cd my-private-folder
python3 -m http.server 3838
经过身份验证的用户应该可以转到http://example.com/app查看 localhost应用程序提供的内容。
应拒绝未经身份验证的用户访问并重定向到登录页面。
Apache有一个指令ProxyPass
,可以在请求发送到目标之前修改请求中的HTTP头。它还有一个指令ProxyPassReverse
,可以在响应返回给用户之前修改响应中的标题。
有没有办法模仿Apache在PHP中的行为?
使用Laravel PHP框架有一种简单的方法吗?
作为参考,有一个名为oxy的包在Go中实现了这个目标。我不知道PHP的等效包。
以下是我在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
我希望资源从http://localhost:3838/resource.jpg传递到http://example.com/app/resource.jpg
相反,该应用程序发出失败请求以获取http://example.com/resource.jpg
要了解失败的原因,请参阅下面正确运行的Apache解决方案。 Apache有一个名为ProxyPassReverse的指令来修改HTTP头,因此localhost应用程序从正确的URL请求资源。
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>
这个相关的答案帮助我更好地理解ProxyPassReverse
指令的工作原理:
答案 0 :(得分:0)
如果问题仅出在资产上,您可以将它们路由到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)');
答案 1 :(得分:0)
我认为Jens Segers有一个软件包可以让PHP模仿ProxyPass
指令:https://github.com/jenssegers/php-proxy
以下是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);