Apache-2.4

基於自定義 Header (Apache) 的授權

  • April 26, 2019

我有一個在 Apache 反向代理後面執行的服務,它使用自定義標頭“使用者名”和“角色”來辨識使用者及其角色。

我希望 Apache HTTPD 限制對自定義 HTTP 標頭“groupmembership”包含以下之一的人的訪問:“viewer”、“publisher”、“administrator”。

Apache 位於另一個代理之後,該代理對使用者進行身份驗證並填充 HTTP 標頭“使用者名”和“組成員”,其中“組成員”的內容是逗號分隔的組列表。

作為參考,我已經包含了架構的草案。 http-proxy-auth

這怎麼可能?我嘗試使用像Require expr %{HTTP:iv_groupmembership} in { 'viewer', 'publisher', 'administrator' }inside這樣的 require 指令<Location />,但無濟於事。

這可以與 mod_rewrite 一起使用嗎?

這是使用 mod_proxy 和 mod_rewrite 的反向代理配置:

RewriteEngine on
<Proxy *>
 Allow from all
</Proxy>
ProxyRequests Off

# store variable values with dummy rewrite rules
RewriteRule . - [E=req_scheme:%{REQUEST_SCHEME}]
RewriteRule . - [E=http_host:%{HTTP_HOST}]
RewriteRule . - [E=req_uri:%{REQUEST_URI}]

# set header with variables
RequestHeader set X-RSC-Request "%{req_scheme}e://%{http_host}e%{req_uri}e"

RewriteCond %{HTTP:Upgrade} =websocket
RewriteRule /(.*) ws://localhost:3939/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket
RewriteRule /(.*) http://localhost:3939/$1 [P,L]
ProxyPass / http://172.17.0.1:3939/  
ProxyPassReverse / http://172.17.0.1:3939/

感謝您的任何提示。

編輯:基本上,問題歸結為:如何檢查groupmembership標題中以逗號分隔的列表是否包含“管理員”、“發布者”或“查看者”

這應該這樣做。如果您在 header 中有一個逗號分隔的列表groupmembership,則使用第一個正則表達式。列表中的一個值必須匹配才能授予訪問權限。

如果要匹配 中的確切值iv_groupmembership,請取消註釋第二個第三個表達式(並註釋第一個)。

編輯:

  • 添加RequestHeader set role範例,根據需要取消註釋。我只測試了這個Header set role(在響應中,沒有後端),但應該以RequestHeader相同的方式工作。

編輯2:

  • <Location/>為清楚起見已刪除
  • 添加了X-Auth-Token檢查的範例groupmembership

範例配置:

   # test for string in comma-separated values, one of the values must match
   <If "%{HTTP:groupmembership} !~ /(^|,)(viewer|publisher|administrator)(,|$)/">

   # combined: X-Auth-Token must be set or one of the roles must exist
#   <If "%{HTTP:X-Auth-Token} == '' && %{HTTP:groupmembership} !~ /(^|,)(viewer|publisher|administrator)(,|$)/">

   # alternative: test for a single value in "iv_groupmembership" (exact match)
#   <If "! %{HTTP:iv_groupmembership} in { 'viewer', 'publisher', 'administrator' }">

       Require all denied
   </If>

   # set role of groupmembership
#   <If "%{HTTP:groupmembership} =~ /(^|,)viewer(,|$)/">
#       RequestHeader set role viewer
#   </If>
#   <ElseIf "%{HTTP:groupmembership} =~ /(^|,)publisher(,|$)/">
#       RequestHeader set role publisher
#   </ElseIf>
#   <ElseIf "%{HTTP:groupmembership} =~ /(^|,)administrator(,|$)/">
#       RequestHeader set role administrator
#   </ElseIf>

   # set role of iv_groupmembership
#   RequestHeader set role "expr=%{HTTP:iv_groupmembership}"

修改 Apache 中的標頭(如RequestHeader set iv_groupmembership "viewer")以調試/測試配置不起作用,您需要儘早設置標頭。

https://httpd.apache.org/docs/2.4/expr.html#vars

表達式解析器提供了許多 %{HTTP_HOST} 形式的變數。請注意,變數的值可能取決於對其求值的請求處理階段。例如,在完成身份驗證之前評估 <If > 指令中使用的表達式。因此,在這種情況下不會設置 %{REMOTE_USER}。

您可以從命令行使用 wget 測試配置,替換localhost為您的主機名。

# HTTP/1.1 403 Forbidden
wget -S -O - http://localhost
wget -S -O - --header='groupmembership: xviewer' http://localhost
wget -S -O - --header='groupmembership: administratorx' http://localhost
wget -S -O - --header='iv_groupmembership: xviewer' http://localhost

# HTTP/1.1 200 OK
wget -S -O - --header='groupmembership: foo,viewer' http://localhost
wget -S -O - --header='groupmembership: publisher,foo' http://localhost
wget -S -O - --header='iv_groupmembership: viewer' http://localhost
wget -S -O - --header='iv_groupmembership: publisher' http://localhost
wget -S -O - --header='iv_groupmembership: administrator' http://localhost

使用 Apache/2.4.25 (Debian) 測試

引用自:https://serverfault.com/questions/964521