前言
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 的解决方案主要包含以下三点:
- 利用 Apache 与 LDAP 或其他用户系统集成来验证权限;
- 利用 Apache 的日志功能来记录所有验权动作以及用户行为;
- 利用 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 认证模块
- 准备好日志目录和默认日志文件
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
命令来运行一个实例。
# 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