macfly / yii2-webserver-auth
为Yii框架提供的Nginx和Httpd认证模块
Requires
- macfly/yii2-filter-auth-cookie: *
- yiisoft/yii2: ~2.0.13
README
此模块允许您限制对Nginx或Apache HTTPD服务器后面任何网站的访问。使用此模块,您的Yii网站将成为您的认证和授权提供者,就像LDAP或htaccess文件一样。
一些有用的用法
- 在多个Web服务器上共享登录和密码(无需在各个地方更新htaccess以更新密码),可以直接在您的Yii网站上完成。
- 如果HTTPD或Nginx后面的网站不在HTTPS上,认证基于访问令牌(默认情况下),如果您的令牌寿命不长且随机,它可以接受用于安全目的(始终建议使用ssl)。
- 在Nginx中,您有单点登录功能,如果您已经登录到您的Yii网站,您将看不到任何登录页面(仅在所有网站都共享父域名以访问cookie时才有效)。
- 权限管理同一个账户可以访问不同的网站,可以访问site1但不能访问site2。
测试
在example
目录中有一个Apache HTTPD和Nginx的完整docker-compose示例,只需执行
git clone https://github.com/marty-macfly/yii2-webserver-auth.git cd yii2-webserver-auth/example/yii composer update cd .. docker-compose build docker-compose up
yii站点只是安装了扩展的yii基本模板
您可以访问以下组件
- Yii: http://127.0.0.1:8080
- Nginx: http://127.0.0.1:8888
- Httpd: http://127.0.0.1:8889
有两个用户
- admin/admin => 访问令牌:100-token
- demo/demo => 访问令牌:101-token
登录和密码仅用于Nginx上的单点登录,当您重定向到http://127.0.0.1:8080/site/login时。如果您的浏览器直接提示登录和密码,您应使用登录:x-sso-token
(在模块配置中定义的token_name
的名称)和访问令牌作为密码(对于admin用户100-token
)。
Yii设置
安装
通过composer安装此扩展是首选方式。
运行以下命令之一
php composer.phar require --prefer-dist "macfly/yii2-webserver-auth" "*"
或添加
"macfly/yii2-webserver-auth": "*"
到您的composer.json
文件的require部分。
配置
按照以下方式配置config/web.php
'modules' => [ ................ 'htaccess' => [ 'class' => 'macfly\yii\webserver\Module', // 'token_name' => 'mycookie', // You can change the name of the login/cookie/header in which the authentication token will be set/get ], ................ ],
模块 bootstrap 将在 user
组件处理器的 macfly\yii\webserver\events\NginxAuthEvent->setTokenCookie
上附加于 afterLogin
,并在 macfly\yii\webserver\events\NginxAuthEvent->unsetTokenCookie
上附加于 afterLogout
。
Nginx 配置
安装
您需要安装 Nginx Auth Request 模块 ngx_http_auth_request_module
- 在 Debian 上,该模块由
nginx-extras
提供,因此要安装,您只需执行以下操作
apt-get install nginx-extras
配置
您需要更新您想要限制的站点的 Nginx 配置,添加以下元素
server {
listen 80;
server_name www.website.com;
location / {
# We want to protect the root of our website
auth_request /auth;
root /usr/share/nginx/html;
index index.html index.htm;
error_page 401 = @error401;
error_page 403 = @error403;
}
location @error401 {
# If you want the user to come back here after successful login add
# the following query string "?return_url=http://www.website.com"
return 302 http://yii.website.com/site/login?return_url=${scheme}://${http_host}${request_uri};
# If you don't want the user to be redirect back just remove
# the query string
# return 302 http://yii.website.com/site/login;
}
location @error403 {
return 403;
}
location = /auth {
internal;
rewrite ^(.*)$ /htaccess/auth? break;
proxy_pass http://yii.website.com;
proxy_pass_request_headers on;
# Don't forward useless data
proxy_pass_request_body off;
proxy_set_header Content-Length "";
}
}
您可以在 example/nginx/
目录中找到更详细的 配置。
使用方法
从浏览器访问
当您访问 http://www.website.com 时,如果您没有定义由 token_name
(默认:x-sso-token)或 identityCookie
定义的 cookie,您的浏览器将被重定向到 http://yii.website.com/site/login。登录后,您可以再次访问 http://www.website.com 并获得对站点的访问权限(如果您的用户具有相应的权限)。
从命令行访问
您也可以使用命令行工具(如 wget
或 curl
)进行身份验证,在这种情况下,您可以使用两种方法
- 通过 HTTP Bearer Tokens 提供访问令牌
$ curl -s -i -X GET --header 'Authorization: Bearer 100-token' 'http://127.0.0.1:8888/user-sso/' HTTP/1.1 200 OK Server: nginx/1.10.3 Date: Tue, 28 Nov 2017 05:33:01 GMT Content-Type: text/html Content-Length: 359 Last-Modified: Mon, 27 Nov 2017 10:19:20 GMT Connection: keep-alive ETag: "5a1be6a8-167" Accept-Ranges: bytes <!DOCTYPE html> <html>% <head> <title>Welcome to restricted section!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to restricted section!</h1> <p>You can see this page because you're a logged in user, sso was used.</p> </body> </html>
使用无效的令牌
$ curl -s -i -X GET --header 'Authorization: Bearer bad-token' 'http://127.0.0.1:8888/user-sso/' HTTP/1.1 401 Unauthorized Server: nginx/1.10.3 Date: Tue, 28 Nov 2017 05:35:18 GMT Content-Type: application/octet-stream Content-Length: 57 Connection: keep-alive Unauthorized: You didn't provide the authentication token
如果您没有权限访问位置(仅在 sso 模式下,如果您使用 no-sso 测试,则返回代码将为 401)
$ curl -s -i -X GET --header 'Authorization: Bearer 100-token' 'http://127.0.0.1:8888/permission-sso/' HTTP/1.1 403 Forbidden Server: nginx/1.10.3 Date: Tue, 28 Nov 2017 05:36:01 GMT Content-Type: application/octet-stream Content-Length: 61 Connection: keep-alive Forbidden: You don't have permissions to access that resource
- 提供登录/密码的访问令牌,访问令牌作为用户名发送
$ curl -s -i -X GET 'http://100-token:@127.0.0.1:8888/user/' HTTP/1.1 200 OK Server: nginx/1.10.3 Date: Tue, 28 Nov 2017 05:39:52 GMT Content-Type: text/html Content-Length: 359 Last-Modified: Mon, 27 Nov 2017 10:19:20 GMT Connection: keep-alive ETag: "5a1be6a8-167" Accept-Ranges: bytes <!DOCTYPE html> <html> <head> <title>Welcome to restricted section!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to restricted section!</h1> <p>You can see this page because you're a logged in user, sso was used.</p> </body> </html>
Apache Httpd 配置
安装
您需要安装并启用模块 mod_authnz_external。
- 在 Debian 上,该模块由
libapache2-mod-authnz-external
提供,因此要安装,您只需执行以下操作
apt-get install libapache2-mod-authnz-external
由于我们使用 shell 脚本来进行请求,因此您还需要安装 curl
。
apt-get install curl
您需要将脚本 apache-auth.sh
放置在服务器上,该脚本将启动适当的 curl 命令
配置
您需要更新您想要限制的站点的 Httpd 服务器配置,添加以下元素
<VirtualHost *:80>
ServerName www.website.com
DocumentRoot /var/www/html
DefineExternalAuth auth pipe '/apache-auth.sh http://yii.website.com/htaccess/auth'
<Directory "/var/www/html/user">
Options Indexes FollowSymLinks
AuthType Basic
AuthName "Authentication Required"
Require valid-user
AuthBasicProvider external
AuthExternal auth
AllowOverride None
</Directory>
</VirtualHost>
您可以在 example/httpd/
目录中找到更详细的 配置。
从命令行访问
您也可以使用命令行工具(如 wget
或 curl
)进行身份验证,在这种情况下,您可以使用以下方法
- 提供登录/密码的访问令牌,访问令牌作为用户名发送
$ curl -s -i -X GET 'http://100-token:@127.0.0.1:8889/user/' HTTP/1.1 200 OK Date: Tue, 28 Nov 2017 05:44:46 GMT Server: Apache/2.4.25 (Debian) Last-Modified: Mon, 27 Nov 2017 10:58:40 GMT ETag: "159-55ef4c8f3b800" Accept-Ranges: bytes Content-Length: 345 Vary: Accept-Encoding Content-Type: text/html <!DOCTYPE html> <html> <head> <title>Welcome to restricted section!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to restricted section!</h1> <p>You can see this page because you're a logged in user.</p> </body> </html>
使用无效的令牌
$ curl -s -i -X GET 'http://bad-token:@127.0.0.1:8889/user/' HTTP/1.1 401 Unauthorized Date: Tue, 28 Nov 2017 05:45:27 GMT Server: Apache/2.4.25 (Debian) WWW-Authenticate: Basic realm="Authentication Required" Content-Length: 458 Content-Type: text/html; charset=iso-8859-1 <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>401 Unauthorized</title> </head><body> <h1>Unauthorized</h1> <p>This server could not verify that you are authorized to access the document requested. Either you supplied the wrong credentials (e.g., bad password), or your browser doesn't understand how to supply the credentials required.</p> <hr> <address>Apache/2.4.25 (Debian) Server at 127.0.0.1 Port 8889</address> </body></html>