Apache,mod_auth_kerb,mod_proxy:在Go Web应用程序中获取经过身份验证的用户

huangapple go评论94阅读模式
英文:

Apache, mod_auth_kerb, mod_proxy: Get authenticated user in Go Web Application

问题

我正在使用Apache作为反向代理,用于在Go HTTP服务器前进行身份验证等操作。

以下是使用Apache Kerberos设置的代码,但存在一个问题。我不知道如何在我的Go应用程序中获取经过身份验证的用户名。

httpd.conf:

<VirtualHost host.domain.com:80>
  ProxyPreserveHost On
  ProxyPass / http://127.0.0.1:9000/
  ProxyPassReverse / http://127.0.0.1:9000/

  <Location />
    ## gzip
    ##
    AddOutputFilterByType DEFLATE text/html

    Order                      deny,allow
    Allow                      from all

    AuthType                   Kerberos
    AuthName                   "User Admin"
    KrbAuthRealms              DOMAIN.COM
    Krb5Keytab                 /etc/host.krb5keytab
    KrbMethodNegotiate         on
    KrbAuthoritative           on
    KrbMethodK5Passwd          off
    KrbLocalUserMapping on
    KrbSaveCredentials         on
    require valid-user
  </Location>
</VirtualHost>

使用

 AuthType                    basic

我可以通过Go函数

func (*Request) BasicAuth

从请求的Authorization头部获取用户名,但是使用Authorization头部的Negotiate方式就不行了。此外,我无法使用REMOTE_USER环境变量,因为没有CGI环境。我还尝试设置RequestHeader,但没有成功。

有没有办法从Go应用程序中获取经过授权的用户名?

英文:

I'm using Apache as reverse proxy for things like authentication in front of the go http server.

The following apache kerberos setup works with one problem. I don't know how to get the authenticated username in my go application.

httpd.conf:

&lt;VirtualHost host.domain.com:80&gt;
  ProxyPreserveHost On
  ProxyPass / http://127.0.0.1:9000/
  ProxyPassReverse / http://127.0.0.1:9000/

  &lt;Location /&gt;
    ## gzip
    ##
    AddOutputFilterByType DEFLATE text/html

    Order                      deny,allow
    Allow                      from all

    AuthType                   Kerberos
    AuthName                   &quot;User Admin&quot;
    KrbAuthRealms              DOMAIN.COM
    Krb5Keytab                 /etc/host.krb5keytab
    KrbMethodNegotiate         on
    KrbAuthoritative           on
    KrbMethodK5Passwd          off
    KrbLocalUserMapping on
    KrbSaveCredentials         on
    require valid-user
  &lt;/Location&gt;
&lt;/VirtualHost&gt;

With

 AuthType                    basic

I get the username from the request's Authorization header with the go function

func (*Request) BasicAuth

but with Authorization header negotiate this is not possible. Furthermore I'm not able to use the REMOTE_USER environment variable because there is no cgi environment. I also tried to set the RequestHeader but without any success.

Is there any possibility to get the authorized username from the go application?

答案1

得分: 5

抱歉耽搁了一下,我之前忙于其他项目。非常感谢您的建议。在切换到CentOS 7/httpd 2.4环境后,以下解决方案对我来说现在可行:

<VirtualHost host.domain.com:80>

  <Location />
    ## gzip                                                                                          
    ##                                                                                               
    AddOutputFilterByType DEFLATE text/html

    AuthType                   Kerberos
    AuthName                   "Web Application"
    KrbAuthRealms              DOMAIN.COM
    Krb5Keytab                 /etc/host.krb5keytab
    KrbMethodNegotiate         on
    KrbAuthoritative           on
    KrbMethodK5Passwd          off
    KrbLocalUserMapping        on
    KrbSaveCredentials         on
    require valid-user

    RequestHeader unset X-Forwarded-User
    RewriteEngine On
    RewriteCond %{LA-U:REMOTE_USER} (.+)
    RewriteRule .* - [E=RU:%1]
    RequestHeader add X-Forwarded-User %{RU}e
  </Location>

  ProxyPreserveHost On
  ProxyPass / http://127.0.0.1:8000/
  ProxyPassReverse / http://127.0.0.1:8000/

  ServerName host.domain.com
 </VirtualHost>

可以使用以下代码在Go中访问用户:

user := req.Header.Get("X-Forwarded-User")
英文:

Sorry for the delay - I was involved in other projects. Many thanks for the suggestions. The following solution now works for me after switching to the environment CentOS 7/httpd 2.4:

&lt;VirtualHost host.domain.com:80&gt;

  &lt;Location /&gt;
    ## gzip                                                                                          
    ##                                                                                               
    AddOutputFilterByType DEFLATE text/html

    AuthType                   Kerberos
    AuthName                   &quot;Web Application&quot;
    KrbAuthRealms              DOMAIN.COM
    Krb5Keytab                 /etc/host.krb5keytab
    KrbMethodNegotiate         on
    KrbAuthoritative           on
    KrbMethodK5Passwd          off
    KrbLocalUserMapping        on
    KrbSaveCredentials         on
    require valid-user

    RequestHeader unset X-Forwarded-User
    RewriteEngine On
    RewriteCond %{LA-U:REMOTE_USER} (.+)
    RewriteRule .* - [E=RU:%1]
    RequestHeader add X-Forwarded-User %{RU}e
  &lt;/Location&gt;

  ProxyPreserveHost On
  ProxyPass / http://127.0.0.1:8000/
  ProxyPassReverse / http://127.0.0.1:8000/

  ServerName host.domain.com
 &lt;/VirtualHost&gt;

The user can be accessed in Go with:

user := req.Header.Get(&quot;X-Forwarded-User&quot;)

答案2

得分: 1

请不要使用重写解决方法,因为如果使用类似mod_authn_ntlm(ntlm与本地计算机)的模块设置了REMOTE_USER,您将在执行阶段遇到问题(请参阅https://support.microsoft.com/en-us/kb/896861)。

RewriteCond %{LA-U:REMOTE_USER} (.+)
RewriteRule . - [E=RU:%1]
RequestHeader set X-Remote-User %{RU}e

而是使用以下方法:

RequestHeader set X-Remote-User expr=%{REMOTE_USER}
英文:

do NOT use the rewrite workaround, because you will get into trouble with execution phases if the REMOTE_USER is set with a module like mod_authn_ntlm (ntlm with local computer, see https://support.microsoft.com/en-us/kb/896861).

RewriteCond %{LA-U:REMOTE_USER} (.+)
RewriteRule . - [E=RU:%1]
RequestHeader set X-Remote-User %{RU}e

instead use the following method:

RequestHeader set X-Remote-User expr=%{REMOTE_USER}

答案3

得分: 0

你可以通过SetEnvIf来设置一个头部 - http://httpd.apache.org/docs/2.2/mod/mod_setenvif.html#setenvif - 如下所示:

SetEnvIf Authorization &quot;(.*)&quot; HTTP_APP_USER=$1

然后你可以通过r.Header.Get(&quot;HTTP_APP_USER&quot;)在Go中访问它。

请注意,不能保证客户端没有同时设置相同的头部:http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#x-headers

> 在使用这些头部时要小心,因为如果原始请求已经包含了这些头部,它们将包含多个(逗号分隔的)值。例如,你可以在源服务器的日志格式字符串中使用%{X-Forwarded-For}i来记录原始客户端的IP地址,但如果请求通过多个代理,你可能会得到多个地址。

英文:

You should be able to set a header via SetEnvIf - http://httpd.apache.org/docs/2.2/mod/mod_setenvif.html#setenvif - as below:

SetEnvIf Authorization &quot;(.*)&quot; HTTP_APP_USER=$1

You can then access it in Go via r.Header.Get(&quot;HTTP_APP_USER&quot;).

Beware that there's no guarantee the client hasn't also set a header with the same: http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#x-headers

> Be careful when using these headers on the origin server, since they will contain more than one (comma-separated) value if the original request already contained one of these headers. For example, you can use %{X-Forwarded-For}i in the log format string of the origin server to log the original clients IP address, but you may get more than one address if the request passes through several proxies.

答案4

得分: 0

尝试以下配置,然后您应该在头部的X-Forwarded-User中看到您的用户名。确保已加载头部模块,例如a2enmod headers

<VirtualHost host.domain.com:80>

  <Location />
    ## gzip
    ##
    AddOutputFilterByType DEFLATE text/html

    AuthType                   Kerberos
    AuthName                   "User Admin"
    KrbAuthRealms              DOMAIN.COM
    Krb5Keytab                 /etc/host.krb5keytab
    KrbMethodNegotiate         on
    KrbAuthoritative           on
    KrbMethodK5Passwd          off
    KrbLocalUserMapping        on
    KrbSaveCredentials         on
    require valid-user
    RequestHeader              set X-Forwarded-User %{REMOTE_USER}s    
  </Location>

  ProxyPreserveHost On
  ProxyPass / http://127.0.0.1:9000/
  ProxyPassReverse / http://127.0.0.1:9000/

</VirtualHost>
英文:

Try the following config, you should then see your username in the header X-Forwarded-User. Make sure the headers module is loaded e.g. a2enmod headers:

&lt;VirtualHost host.domain.com:80&gt;

  &lt;Location /&gt;
    ## gzip
    ##
    AddOutputFilterByType DEFLATE text/html

    AuthType                   Kerberos
    AuthName                   &quot;User Admin&quot;
    KrbAuthRealms              DOMAIN.COM
    Krb5Keytab                 /etc/host.krb5keytab
    KrbMethodNegotiate         on
    KrbAuthoritative           on
    KrbMethodK5Passwd          off
    KrbLocalUserMapping        on
    KrbSaveCredentials         on
    require valid-user
    RequestHeader              set X-Forwarded-User %{REMOTE_USER}s    
  &lt;/Location&gt;

  ProxyPreserveHost On
  ProxyPass / http://127.0.0.1:9000/
  ProxyPassReverse / http://127.0.0.1:9000/

&lt;/VirtualHost&gt;

huangapple
  • 本文由 发表于 2015年5月10日 22:13:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/30152416.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定