先吐槽一下,国内技术博文好多要不是过时,要不就是互相复制,搜来搜去没一个解决了问题的。
以下内容是按照自己的思考过程来写的额。
1. 背景
前端使用 VS Code 开发网页时,会借助插件 Live-Server 热加载进行快速开发,同时也避免了跨域带来的开发问题。
在研究 Live-Sever 时,发现其通过 WebSocket 实现热加载,借助插件 server-index & server-static 来托管服务器静态资源和实现文件资源列表展示。于是想到 Http 服务器 Apache Httpd,它是静态服务器,顾名思义就是它也是托管静态文件资源的,我们所看到的网页不过是服务器某个文件目录下的HTML类型的文件,返回给请求端并被浏览器渲染所得。如果不做任何限制的话,我们是能够通过在地址栏直接输入 URL 访问指定服务器文件或者某个文件夹下内容的。
想来,互联网大世界,Web 时代,我们看到的形形色色的网页不过是别人上传到站点上的静态文件。
也确实如此,起初的 Http 服务器只支持访问静态资源,比如看个 html 页面啥的,因为最先就是为了实现共享技术文档等知识的,功能够用了。HTTP 协议的产生及最早的 Http 服务器 CERN Httpd 见文章。
后来的HTTP服务器像 NCSA 服务器是开发了自己的版本,因为 CERN Httpd 的一些缺点,例如不适合很多平台,但NCSA 服务器风靡过后但也停止发展了。最初的 Apache Httpd 是用 NCSA 工具开发的,但是现在的 Apache Httpd 早已完全重写过了,不是最初的 Apache Httpd 了。
然后将目标瞄准了 Apache Httpd,本来想去其官网下载安装包本地安装的,但Mac 内置了 Httpd 服务器,索性就用它了。
2. Built-in Httpd
我的 Mac OS 是 Monterey 12.3.1,内置了 Apache Httpd,查看其版本信息如下:
apachectl -v
或
httpd -v
Server version: Apache/2.4.51 (Unix)
软件一般都有配置文件,用来供用户自定义配置,这种 ”放权“ 赋予了用户一定的自由度,也是优秀设计的特征之一。
如下图1,配置文件在目录 /etc/apache2 下,文件名为 httpd.conf【到了版本3估摸目录就是 /etc/apache3 了】。因为是 Mac OSX 自带的,是以 root 用户安装的,所以对配置文件的修改都需要“索权”,以 root 的身份进行修改。

3. 修改 httpd.conf —— DocumentRoot
配置文件 httpd.conf 中有一段配置信息如下所示,字段 DocumentRoot 表示的是提供文档的目录。默认情况下,所有请求都取自该目录,但是也可以使用符号链接或者别名指向其它的位置。
#
# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
DocumentRoot "/Library/WebServer/Documents"
<Directory "/Library/WebServer/Documents">
...
</Directory>
为了开发方便,想将 Document 字段后面的字符串更改为我的项目文件夹路径。不管项目文件放哪儿,绝对路径前缀都会有 /Users/用户名
,其中用户名是我们当前登录系统的用户名,我们的操作都是在 /Users/用户名 目录下进行的。以下用我的 OSX 下操作来说明。
对于 DocumentRoot 我的更改如下所示。
DocumentRoot "/Users/foiunclekay/Documents/GitHub/estatewebsite_user_frontend"
<Directory "/Users/foiunclekay/Documents/GitHub/estatewebsite_user_frontend">
...
</Directory>
问题来了,重启后访问报错如下图2所示,提示没有权限访问资源,也就是启动运行 Apache 的那个用户没有权限。

如下所示,这段配置信息就是用来配置运行 httpd 的用户/用户组的,默认是以用户 _www:_www 运行 Apache 的。其实我们使用命令 sudo apachectl start
启动 Apache,是先以 root 用户身份启动的 Apache,然后再转换为 _www 用户的。所以 root 用户和 _www 用户的 httpd 进程都存在。系统建议我们为不同的服务单独创建特定的运行用户/用户组,这不,为运行 Apache Httpd 创建的 _www:_www。
<IfModule unixd_module>
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.
# User/Group: The name (or #number) of the user/group to run httpd as.
# It is usually good practice to create a dedicated user and group for
# running httpd, as with most system services.
User _www
Group _www
</IfModule>
所以我看了看路径 /Users/foiunclekay/Documents/GitHub/estatewebsite_user_frontend
对于用户 _www 的执行权限,我查看了每一级的文件目录权限都是 755,那说明用户 _www 至少拥有读权限和执行权限,不应该是因为这个用户的问题。
有人不信,那好,我把上面的配置 User
改为文件/文件夹拥有者 foiunclekay
,用户组 Group
改为 staff
,然后重启运行依然是报错没有访问权限,这就很奇怪了啊,已经用文件资源的拥有者启动 Apache了还报没有权限的错误。
网上查了一圈,要不就是让给当前运行 Apache 用户赋予权限的,要不就是更改以下配置信息的,显然都没有用。【提示:好多过期博文所说的改Order deny, allow Deny from all
啥的,其实就用一句Require all granted
就能代替,后者是 Apache 最新版本的表述】
<Directory "/Users/foiunclekay/Documents/GitHub/estatewebsite_user_frontend">
Options FollowSymLinks Multiviews
MultiviewsMatch Any
AllowOverride None
Require all granted
</Directory>
然后我重新逐级查看文件夹权限信息,如下图3所示,第一列表示文件夹 /Users/foiunclekay 的权限信息,d 表示文件夹是目录类型,权限为 755,但最后的 加号+
是啥?
加号+ 其实表示这个目录还使用了 ACL 权限管理。除了 /Users/foiunclekay 目录,/Users/Guest 目录也有 ACL 权限管理。也确实如此,将 DocumentRoot 路径改成访问 /Users/Guest 目录下的内容,同样报权限错误。

我试着将 DocumentRoot
路径改成不在/Users/foiunclekay 和 /Users/Guest
目录下,发现可以访问
,目前看来可能跟这个 ACL 有关。
可是我看了看文件夹的 ACL 权限信息如下所示。
ls -le
0: group:everyone deny delete
只有一个 ACL Entry,而且说的是任何人都不能删除该文件夹,这跟 Apache 用户没有访问权限没有关系吧?
于是,抱着不管怎样得试试的心态...如下所示,我把 ACL 权限信息给删除了,可结果依然是报403无权限访问的错误。
sudo chmod -a 'group:everyone deny delete' foiunclekay/
看来跟这个 ACL 没有关系,于是我往下一级目录 /Documents 继续扒。
ll |grep Documents/
drwxr-xr-x@ 15 foiunclekay staff 480 Oct 14 23:43 Documents
Documents 目录的信息如上所示,文件权限的末尾符号 @
是什么?
这个@符号表示文件有一些扩展属性,这些属性是一种元数据,存储在HFS文件系统的特殊位置,通常情况下是不可见的。很多流行的文件系统都支持元数据,其实除了符号@,还有符号+,它们都是一种非标准的权限,所谓“非标准”,你看windows 或 linux 中就没有。
如下所示,借助命令行工具 xattr 能够查看文件的扩展属性信息。
xattr Documents/
com.apple.macl
我借着命令xattr -d com.apple.macl Documents/
想要删除扩展属性试试的,发现短暂删除后,该属性又自行恢复了,apache 用户依然没访问权限。
我将 DocumentRoot 改成 Documents 同级目录下没有 com.apple.macl 扩展属性的文件夹,发现 apache 用户可以访问了,看来跟这个扩展属性有关系,那么com.apple.macl 这个扩展属性是什么呢?
其实,有三个扩展属性在安全和隐私方面扮演着重要的角色:com.apple.quarantine、com.apple.rootless 和 com.apple.macl。扩展属性 com.apple.macl 是受 SIP(System Integrity Protection) 保护的,所以咱删除不掉这个扩展属性,除非你关闭 SIP
。
OSX 的 MACL 是 OSX 比较隐蔽的一个功能,也是Apple User-Intent的基础。User-Intent 是 OS X 隐私控制方面的一个改进,目的是避免过多的提示,干扰用户对系统的正常使用。
如果想要继续深入了解,自行研究。
总结来说,修改的 DocumentRoot 路径中不能含带有 com.apple.macl 扩展属性
的目录。可以通过查看文件权限信息后是否有@符号并通过命令xattr 目录名
来确定是否是 com.apple.macl 扩展属性。如果有,可以换一个不带该扩展属性的文件目录即可,不建议强制去删除这个扩展属性。
参考资料:
https://eclecticlight.co/2020/01/30/quarantine-sip-and-macl-macos-per-file-security-controls/
https://mjtsai.com/blog/2019/12/18/persistent-file-access-via-com-apple-macl-xattr/
https://blog.xpnsec.com/we-need-to-talk-about-macl/
https://zhuanlan.zhihu.com/p/37221636
网友评论