LDAP 集成之 Apache 篇

2022-10-28 11:17:07 浏览数 (1)

前言

Apache

  Apache HTTP 服务器作为当今流行的几大 HTTP 服务器之一,几乎占据了半壁江山。与知名的Nginx(现已被 F1 收购)、微软的 IIS 相比,Apache 具有更好的模块化支持,无论是从服务端的编程语言还是到身份认证方案。Apache 支持 Perl、Python、PHP 等常用服务端语言,同时也支持 Basic 认证、LDAP 认证、OAuth 2.0 等。尤其是 LAMP(Linux Apache MySQL PHP)集成环境已经成为了虚拟主机的首选。当然,也有提供 ASP 虚拟主机环境的。

Apache 与博客发展

  实际上,在博客兴起的初期,大部分博客是最简单的静态页面。而随着服务器端语言的发展,开始有了基于 ASP.net 或 PHP 的博客开源程序,例如最为流行的 WordPress 就是基于 PHP 编写的。在笔者学习博客的初期,也是使用了 WordPress 和 PHP 虚拟主机来搭建自己的博客。可以说,PHP 或 ASP 集成环境在相当一段时间内可能都是最好的博客或者网站解决方案。但随着云服务、无服务计算、Git 等的兴起,以 Git 为中心的持续集成、持续部署的方式越来越成为了搭建个人静态博客的首选。这也反映了博客发展的动态变化过程:静态博客→动态博客→静态博客

  以 Github Page、Gitlab Page、Netlify、Vercel、Cloudflare Page 等为代表的静态站点部署方式越来越受到大家的喜爱,现在大部分大公司的文档都已经转变为这种方式,比如 Azure 的官方文档、Cloudflare 的官方文档、腾讯云的官方文档等。这样一种方式不仅有利于开发的快速迭代,还有利于吸引大众参与到文档的贡献与纠错中来,可以使文档越来越好。当然,这其实就是“开源”的思想。那这是不是就意味着 Apache 对静态网站变得不那么有用了呢?当然不是。Apache 所支持的认证模块、日志模块、重写模块、代理模块等对静态网站也非常重要。

Apache 对文档的妙用

  现在的开发文档大部分都已经采用 Git Markdown SSG(Static Site Generator,静态站点生成器)的方式进行开发部署。对于团队内部的文档可能常常会有权限限制和访问记录的需求,甚至说如果有共享文件,也希望能够知道是谁下载了、在什么时候下载了。如果以后端编程的角度来想,可能需要开发一套系统专门实现验权、访问记录、下载记录、数据统计等功能。即使如此,当有多个文档需要集成到一起时,这种解决方案仍然有点困难了。所以付出了相当的代价,而所获取的收益却不是很明显。针对这一需求,基于 Apache 可以有更加简便的方案,如下图所示:

  如上图所示,基于 Apache 的解决方案主要包含以下三点:

  1. 利用 Apache 与 LDAP 或其他用户系统集成来验证权限;
  2. 利用 Apache 的日志功能来记录所有验权动作以及用户行为;
  3. 利用 Apache 的重写模块和代理模块将所有文档集中在一个域名的不同子目录下。

实践

  为了尽可能简单地实现一下上面所提到的基于 Apache 的文档解决方案,这里采用了 Docker 镜像的方式。

环境准备

  • Docker 环境(推荐 Linux 或 Mac)
  • 已安装 docker-compose 工具

配置文件准备

  如需自行构建 Docker 镜像,请将以下三个配置文件放置在 conf 子目录中。如直接使用下面笔者构建的 zhonger/ldap-apache 镜像,可以忽略。

LDAP 验证定义
代码语言:javascript复制
# ldap-demo.conf

<AuthnProviderAlias ldap demo>
  AuthLDAPBindDN ${LDAP_BindDN}
  AuthLDAPBindPassword ${LDAP_BindPass}
  AuthLDAPURL ${LDAP_URL}
  Require ldap-group ${LDAP_BindGroup}
</AuthnProviderAlias>
激活 LDAP 验证
代码语言:javascript复制
# .htaccess

AuthBasicProvider demo
AuthType Basic
AuthName "Protected Area"
Require valid-user
重写 Apache 配置文件
代码语言:javascript复制
# apache2.conf

DefaultRuntimeDir ${APACHE_RUN_DIR}

PidFile ${APACHE_PID_FILE}

Timeout 300

KeepAlive On

MaxKeepAliveRequests 100

KeepAliveTimeout 5

User ${APACHE_RUN_USER}
Group ${APACHE_RUN_GROUP}

HostnameLookups Off

ErrorLog ${APACHE_LOG_DIR}/error.log

LogLevel warn

# Include module configuration:
IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf

# Include list of ports to listen on
Include ports.conf

<Directory />
    Options FollowSymLinks
    AllowOverride None
    Require all denied
</Directory>

<Directory /usr/share>
    AllowOverride None
    Require all granted
</Directory>

<Directory /var/www/>
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

AccessFileName .htaccess

<FilesMatch "^.ht">
    Require all denied
</FilesMatch>

LogFormat "%v:%p %h %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"" vhost_combined
LogFormat "%h %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"" combined
LogFormat "%h %l %u %t "%r" %>s %O" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent

IncludeOptional conf-enabled/*.conf
IncludeOptional sites-enabled/*.conf

Apache 子目录设置

  之前提到如果有多个文档分别以多个 Git 项目存在,那么最终编译成的静态文件也是分别存放或者分别部署。这里介绍两种子目录的形式:目录假名(Alias)代理(Proxy)

目录假名

  目录假名比较简单,我们可以直接使用以下配置实现方案图中的各个文档目录:

代码语言:javascript复制
...
Alias "/dvm/" "/var/www/dvm/"
Alias "/ds3/" "/var/www/ds3/"
Alias "/dgit/" "/var/www/dgit/"
Alias "/dml/" "/var/www/dml/"
Alias "/dnc/" "/var/www/dnc/"
...
<Directory /var/www/>
...

  由于下面构建的镜像仍采用了上面的 Apache 配置文件,所以不包含以上目录假名设置。如有需要,可以按照上面给出的顺序将目录假名设置加入到新的 apache2.conf 文件中,并且在 docker-compose.yml 文件中如下所示挂载新的 apache2.conf 文件即可生效。

代码语言:javascript复制
...
      volumes:
        - ./data:/var/www/
        - ./logs:/var/log/apache2/
        - /etc/localtime:/etc/localtime
        - ./apache2.conf:/etc/apache2/apache2.conf
...
代理

  下面的构建镜像 Dockerfile 中将会预先启用代理模块,由于可能会代理 HTTPS 端口,所以 HTTP 模块和 SSL 模块也预先启用了。除此之外,如果需要代理 HTTPS 站点,就要像下面一样开启 SSLProxyEngine 配置,否则只能完成 HTTP 代理。代理配置的第二行是“ProxyPass 子目录 代理 URL”。

小提示

需要注意的是应该把代理配置放在目录配置之前。

代码语言:javascript复制
...
SSLProxyEngine On
ProxyPass /foo https://foo.example.com
...
<Directory /var/www/>
...

构建镜像

  Docker 镜像的构建实际上就是要做这么几件事:

  • 复制三个配置文件到容器镜像中
  • 启用 LDAP 认证模块
  • 准备好日志目录和默认日志文件
代码语言:javascript复制
FROM php:7-apache

LABEL maintainer="zhonger zhonger@live.cn"

# Enable ldap for apache2
COPY conf/ldap-demo.conf /etc/apache2/conf-available/ldap-demo.conf

RUN a2enmod authnz_ldap proxy proxy_http ssl && 
    ln -s /etc/apache2/conf-available/ldap-demo.conf /etc/apache2/conf-enabled/ldap-demo.conf

COPY conf/.htaccess /var/www/html/
COPY conf/apache2.conf /etc/apache2/apache2.conf

# Save logs for apache
RUN rm /var/log/apache2/* && 
    cd /var/log/apache2/ && 
    touch access.log error.log

# Remove cache
RUN rm -rf /var/lib/apt/lists/*

EXPOSE 80

  当准备好配置文件和上面的 Dockerfile 文件时,执行 docker build . -t zhonger/ldap-apache 命令构建 Docker 镜像。

运行验证

  构建 Docker 镜像成功后,新建 docker-compose.yml 文件并使用 docker-compose up -d 命令来运行一个实例。

代码语言:javascript复制
# docker-compose.yml

version: '2'

services:
    apache:
      image: zhonger/ldap-apache:latest
      volumes:
        - ./data:/var/www/
        - ./logs:/var/log/apache2/
        - /etc/localtime:/etc/localtime
      environment:
        LDAP_URL: "ldap://ldap.example.com/ou=users,dc=example,dc=com?uid"
        LDAP_BindDN: "cn=admin,dc=example,dc=com"
        LDAP_BindPass: "xxxxxxxxxx"
        LDAP_BindGroup: "ou=people,dc=example,dc=com"
        APACHE_LOG_DIR: "/var/log/apache2"
      ports:
        - 80:80
      restart: always
验证网页

  为了验证 LDAP 认证是否有效,这里写了一个简单的 PHP 文件 /var/www/html/p.php。当没有放置 .htaccess 文件时,无须任何认证即可访问。当在 /var/www/html 目录放置 .htaccess 文件时,浏览器再次访问会弹出如下登录弹窗。正确输入 LDAP 允许的用户名和密码后,浏览器会再次正常显示刚才看到的内容。

代码语言:javascript复制
<!-- p.php -->
<? php
    echo phpinfo();
验证日志

  当查看 Apache 的访问日志 access.log 文件时,可以看到如下内容。第一行是未设置 LDAP 验证时的正常访问记录,第二行是设置 LDAP 验证后提醒登录的记录,第三行是登录成功后带有登录用户名的记录(由于隐私关系,下图遮住了登录用户名)。

验证目录假名

  这里为了验证目录假名,新建了目录 /var/www/dvm,并在目录中新建了内容为 dvm 的 index.html 文件。在配置上面提到的目录假名之后访问浏览器可以看到如下所示效果,正常生效。

验证代理

  这里为了验证代理效果,直接代理了百度首页(虽然这样不大好)。如下所示可以正常看到百度首页内容。

参考资料

  • Apache HTTP 服务器
  • Apache Module mod_alias
  • How To Use Apache HTTP Server As Reverse-Proxy Using mod_proxy Extension

版权声明:如无特别声明,本文版权归 仲儿的自留地 所有,转载请注明本文链接。

(采用 CC BY-NC-SA 4.0 许可协议进行授权)

本文标题:《 LDAP 集成之 Apache 篇 》

本文链接:https://cloud.tencent.com/developer/article/2143061

0 人点赞