Restrict access with Basic and Client Authentication

我在之前的一篇文章中有大概的讲过如何在Apache服务器上使用Client Authentication。最近我在尝试把我写过的文章都录成视频的时候觉得之前写的文章不够详尽,因此专门另外再开一篇详细讲讲到底如何在Apache服务器上使用Basic AuthClient Auth

Basic Auth

Apache服务器的Basic Auth就是使用用户名和密码的传统方式来验证来访的用户。Digitalocean的文章已经写的相当的详细。我在就按照他们的做法来尝试一次让各位看看如何操作。

安装Apache Utilities

笔者用的是Debian 10的服务器,其他服务器的软件安装方式各位看官自己查一下吧

我们使用的Apache的程序叫htpasswd。这个小程序包括在apache2-utils这个包里面。因此我们先把这个包安装好。

1
2
sudo apt-get update
sudo apt-get install apache2 apache2-utils
创建用户名和密码

安装好apache2-utils之后我们现在就可以使用htpasswd这个命令来创建用户名和密码了。在这里我们就跟Digitalocean一致,创建一个隐藏文件叫.htpasswd放在/etc/apache2/这个文件夹下面。

第一次运行命令需要加-c来创建该文件,这里我选择的用户名是admin

1
2
3
4
sudo htpasswd -c /etc/apache2/.htpasswd admin
New password:
Re-type new password:
Adding password for user admin

这样我们就在/etc/apache2/.htpasswd这个文件中创建好了用户名为admin的记录。如果需要添加用户,我们可以使用一下命令来添加用户。

1
2
3
4
sudo htpasswd /etc/apache2/.htpasswd fomm
New password:
Re-type new password:
Adding password for user fomm

接下来我们需要在Apache的virtual host中使用我们刚创建的.htpasswd文件。

首先确保我们virtual host文件已经配置好

我这里使用下面这个简单的不能再简单的80端口的配置。

1
2
3
4
<VirtualHost *:80>
ServerName test.sslfor.fun
DocumentRoot /var/www/html
</VirtualHost>

由于配置跟着文件夹走,因此我们需要用到Directory来告诉服务器哪个文件夹需要加密。我这里单独又创建了一个demo的文件夹放上一起其他的文件做演示。

1
2
3
4
5
6
7
8
9
10
11
<VirtualHost *:80>
ServerName test.sslfor.fun
DocumentRoot /var/www/html

<Directory "/var/www/html/demo">
AuthType Basic
AuthName "Restricted Content"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</Directory>
</VirtualHost>

让我们看看这里具体做了什么。

  • 首先我们告诉服务器我们在/var/www/html/demo这个文件夹要使用Basic的验证方式
  • AuthName指的是当用户连接到服务器上该文件夹的时候服务器给什么样的信息给用户
  • AuthUserFile 说的是我们用哪个文件记载了允许的用户和密码
  • Require valid-user说的是只允许可以通过验证的人才能access这个文件夹

文件夹保存好,我们重启一下服务器。

1
sudo systemctl restart apache2

这个时候我们再次去到/demo这个文件夹就会看到如下图般需要输入用户名密码的弹窗。

client-auth-popup

Client Auth

服务器验证用户的方法除了传统的用户名和密码之外,还可以用Cliet证书来验证。我之前的文章已经简单解释过如何使用Client Authentication,但是那篇文章里面的设置是设置成了全站验证,今天我说说指定某个文件夹做验证跟上面的Basic Auth做对应。

设置好HTTPS

我之前的文章已经写过如何在在Apache服务器上设置HTTPS。

做http转https

为了避免通过80端口访问我们需要保密的文件夹,这里我们在virtual host里面做301转接。把所有的http都转到https。其实这里不需要DocumentRoot "/var/www/html/",放着也无妨。

1
2
3
4
5
<VirtualHost *:80>
ServerName test.sslfor.fun
DocumentRoot "/var/www/html/"
Redirect permanent / https://test.sslfor.fun
</VirtualHost>
配置Virtual Host
添加client ca文件
1
2
3
4
5
<VirtualHost *:443>
...
SSLCACertificateFile "/etc/ssl/client-ca.crt"
...
</VirtualHost>
设置在demo文件夹做验证
1
2
3
4
5
6
7
8
9
10
<VirtualHost *:443>
...
SSLCACertificateFile "/etc/ssl/client-ca.crt"
<Location '/admin'>
SSLVerifyClient require
SSLVerifyDepth 10
SSLOptions +StdEnvVars
</Location>
...
</VirtualHost>
验证客户提供的证书

这里我选择的是验证证书序列号

1
2
3
4
5
6
7
8
<VirtualHost *:443>
...
SSLOptions +StdEnvVars
<RequireAll>
Require expr "%{SSL_CLIENT_M_SERIAL} =~ /058631057C7D03CAB379DE90AA8CA8A6/"
</RequireAll>
...
</VirtualHost>
(Optional) 关闭TLS1.3

如果你使用的服务器支持TLS1.3 (例如Apache on Debian 10),那么Client Authention在Firefox和Chromium核心的浏览器会出错。错误信息为Cannot perform Post-Handshake Authentication. 这个时候为了能够使用Client Authentication,我们需要关闭TLS1.3。

1
sudo vim /etc/apache2/mods-enabled/ssl.conf

然后把

1
2
3
4
5
6
...        
# The protocols to enable.
# Available values: all, SSLv3, TLSv1, TLSv1.1, TLSv1.2
# SSL v2 is no longer supported
SSLProtocol all -SSLv3
...

修改成

1
2
3
4
5
6
...        
# The protocols to enable.
# Available values: all, SSLv3, TLSv1, TLSv1.1, TLSv1.2
# SSL v2 is no longer supported
SSLProtocol all -TLSv1.3
...

然后重启你的Apache即可

以上就是在Apache设置Basic AuthClient Auth的方法。