Linux 笔记 - 第十四章 LAMP 之(二) 环境配置
一、前言
LAMP 环境搭建好之后,其实仅仅是安装上了软件,我们还需要掌握 httpd 和 PHP 的配置。
二、httpd 配置
2.1 创建虚拟主机
我们以搭建 discuz 论坛为例,介绍如何在 Apache 中创建虚拟主机。
下载 discuz 论坛建站程序包之后,解压到指定目录,并删掉无用的文件及目录。
# mkdir /data/www
# cp ComsenzDiscuz-DiscuzX-3.4.zip /data/www/
# cd /data/www
# unzip ComsenzDiscuz-DiscuzX-3.4.zip
# rm -rf ComsenzDiscuz-DiscuzX-3.4.zip
# cd DiscuzX
# rm -rf readme utility README.md
# mv upload/* .
# rm -rf upload
编辑 httpd 的主配置文件:/usr/local/apache24/conf/httpd.conf
去掉#号,修改为:
保存后,编辑虚拟主机配置文件:/usr/local/apache24/conf/extra/httpd-vhosts.conf,其中 ServerAdmin 为服务器管理员的邮箱;DocumentRoot为虚拟主机站点的根目录;ServerName 为网站的域名,只能定义一个;ServerAlias 为域名的别名,可以写多个,用分号分隔;ErrorLog 为站点的错误日志,Customer 为站点的访问日志。
<VirtualHost *:>
#ServerAdmin webmaster@dummy-host.example.com
DocumentRoot "/data/www/DiscuzX"
ServerName www.lamper.com
ServerAlias lamper.com
ErrorLog "logs/www.lamper.com-error_log"
CustomLog "logs/www.lamper.com-access_log" common
</VirtualHost>
在启动状态中,可以重新加载 httpd,命令如下:
# apachectl graceful
如果我们在 Windows 中访问我们 Linux 服务器中搭建的 LAMP 应用,可以修改 hosts 文件来自定义域名解析映射,如下:
C:\Windows\System32\drivers\etc\hosts 文件中添加如下映射:
192.168.1.121 www.lamper.com
然后在浏览器中访问:
http://www.lamper.com
自动跳转到discuz安装页面:
点击 "我同意"
发现目录、文件权限检查不符合所需状态,查看 apache 运行进程所属用户为 daemon,如下:
修改上面列出的不符合权限的目录所属主为 daemon,如下:
# chown -R daemon config data uc_client uc_server
修改后,再次刷新刚才的安装页面:
发现已经满足所需的权限了。
点击 "下一步" 后进入:
选择 "全新安装",点击下一步进入安装数据库的页面。
此时,我们先创建数据库和用户:
[root@ryan DiscuzX]# mysql -uroot -p123456
mysql> create database discuz;
Query OK, row affected (0.00 sec)
mysql> grant all on discuz.* to 'rain'@'localhost' identified by '';
Query OK, rows affected, warning (0.00 sec)
mysql> quit
Bye
注意:当数据库存在用户的时候 GRANT 会对用户进行授权,但当数据库不存在该用户的时候,就会创建相应的用户并进行授权。
填入我们创建的数据库和用户:
点击下一步,进入初始化过程中:
初始化完成之后,自动跳入结果页面:
返回我们搭建的轮胎:
2.2 添加用户认证
首先创建密码文件:
[root@ryan extra]# /usr/local/apache24/bin/htpasswd -cm /data/.htpasswd admin
New password:
Re-type new password:
Adding password for user admin
其中 /data/.htpasswd 文件为要创建的密码文件,可自定义路径;htpasswd 命令为创建用户的工具,-c 表示 create 创建,-m 表示使用 MD5 加密方式(默认加密方式),如果是第一次创建时需要使用 -c 选项,第二次时就不需要添加 -c 选项了,否则 /data/.htpasswd 会被覆盖,其余选项可以通过帮助:# /usr/local/apache24/bin/htpasswd --help
[root@ryan extra]# /usr/local/apache24/bin/htpasswd --help
Usage:
htpasswd [-cimBdpsDv] [-C cost] passwordfile username
htpasswd -b[cmBdpsDv] [-C cost] passwordfile username password htpasswd -n[imBdps] [-C cost] username
htpasswd -nb[mBdps] [-C cost] username password
-c Create a new file.
-n Don't update file; display results on stdout.
-b Use the password from the command line rather than prompting for it.
-i Read password from stdin without verification (for script usage).
-m Force MD5 encryption of the password (default).
-B Force bcrypt encryption of the password (very secure).
-C Set the computing time used for the bcrypt algorithm
(higher is more secure but slower, default: , valid: to ).
-d Force CRYPT encryption of the password ( chars max, insecure).
-s Force SHA encryption of the password (insecure).
-p Do not encrypt the password (plaintext, insecure).
-D Delete the specified user.
-v Verify password for the specified user.
On other systems than Windows and NetWare the '-p' flag will probably not work.
The SHA algorithm does not use a salt and is less secure than the MD5 algorithm.
然后在虚拟主机中添加用户认证,可以添加 Directory,表示指定认证的目录信息:
对目录进行用户认证
<VirtualHost *:>
#ServerAdmin webmaster@dummy-host.example.com
DocumentRoot "/data/www/DiscuzX"
ServerName www.lamper.com
ServerAlias lamper.com
ErrorLog "logs/www.lamper.com-error_log"
CustomLog "logs/www.lamper.com-access_log" common
<Directory "/data/www/DiscuzX">
AllowOverride AuthConfig
AuthName "lamper.com user auth"
AuthType Basic
AuthUserFile /data/.htpasswd
require valid-user
</Directory>
</VirtualHost>
其中 Directory 为指定认证的目录,AllowOverride AuthConfig 相当于打开认证的开关, AuthName 自定义认证的名字,AuthType 为认证类型,AuthUserFile 指定密码文件所在位置,require valid-user 说明需要有效的认证用户。
保存后检查配置文件语法正确性并重新加载配置文件:
[root@ryan extra]# apachectl -t
Syntax OK
[root@ryan extra]# apachectl graceful
然后访问 http://www.lamper.com 时,浏览器会弹出对话框进行用户身份验证:
点击取消后,浏览器会提示 401 Unauthorized:
上面添加的配置是对整个站点添加的用户认证,其实用的最多的还是对某个目录或文件进行认证。
对文件进行用户认证
比如对文件认证,在 VirtualHost 中添加 FileMath 如下:
<VirtualHost *:>
#ServerAdmin webmaster@dummy-host.example.com
DocumentRoot "/data/www/DiscuzX"
ServerName www.lamper.com
ServerAlias lamper.com
ErrorLog "logs/www.lamper.com-error_log"
CustomLog "logs/www.lamper.com-access_log" common
<FilesMatch "admin.php">
AllowOverride AuthConfig
AuthName "lamper.com user auth"
AuthType Basic
AuthUserFile /data/.htpasswd # 基于用户的
# AuthGroupFile /data/.htgpasswd # 基于组的
# Require user csr # 只允许csr用户认证
Require valid-user 允许有效用户认证
# Require group group-csr 允许group-csr组认证
</FilesMatch>
</VirtualHost>
注意:FilesMatch 后面的文件是相对路径,而 Files、Directory则使用绝对路径。
也可以将 Directory 中的目录认证直接改为文件据对路径,如下:
<VirtualHost *:>
#ServerAdmin webmaster@dummy-host.example.com
DocumentRoot "/data/www/DiscuzX"
ServerName www.lamper.com
ServerAlias lamper.com
ErrorLog "logs/www.lamper.com-error_log"
CustomLog "logs/www.lamper.com-access_log" common
<Directory "/data/www/DiscuzX/admin.php">
AllowOverride AuthConfig
AuthName "lamper.com user auth"
AuthType Basic
AuthUserFile /data/.htpasswd
require valid-user
</Directory>
</VirtualHost>
验证和重载配置文件:
[root@ryan extra]# apachectl -t
Syntax OK
[root@ryan extra]# apachectl graceful
这样可以使只有我们访问管理员登录页时:http://www.lamper.com/admin.php 才出现用户认证,访问其他页面则不会出现用户认证对话框。
2.3 域名 rewrite 重定向
由于实现域名重定向需要rewrite模块支持,首先查找httpd是否已经加载该模块:
[root@ryan conf]# grep -i rewrite /usr/local/apache24/conf/httpd.conf
#LoadModule rewrite_module modules/mod_rewrite.so
如果没有加载,则将其前面的#号删除,如下:
[root@ryan conf]# vim /usr/local/apache24/conf/httpd.conf
LoadModule rewrite_module modules/mod_rewrite.so
然后在 httpd-vhosts.conf 的 VirtualHost 中添加 rewrite 模块:
[root@ryan conf]# vim /usr/local/apache24/conf/extra/httpd-vhosts.conf
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www.amlinux.com$
RewriteRule ^/(.*)$ http://www.lamper.com/$1 [R=301,L]
</IfModule>
此处将 www.amlinux.com 重定向到 www.lamper.com。
修改 Windows 中的 hosts 文件:
C:\Windows\System32\drivers\etc\hosts
添加如下域名映射,注意同一个IP可以对应多个域名,多个域名之间用空格分隔,如下:
192.168.1.121 www.lamper.com www.amlinux.com
然后验证域名重定向:
当在浏览器中输入 http://www.amlinux.com 后会重新跳转到 http://www.lamper.com;输入 http://www.amlinux.com/123.html 后浏览器会跳转到 http://www.lamper.com/123.html。
如果需要将多个域名重定向到一个域名,则配置多个 RewriteCond 并用 OR 连接,可以将每一个 RewriteCond 看做一个条件表达式,满足这个条件时才执行下面的 RewriteRule 表达式。
多域名重定向,如下:
[root@ryan conf]# vim /usr/local/apache24/conf/extra/httpd-vhosts.conf
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www.amlinux.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.moonxy.com$
RewriteRule ^/(.*)$ http://www.lamper.com/$1 [R=301,L]
</IfModule>
此处将 www.amlinux.com 和 www.moonxy.com 均重定向到 www.lamper.com。
如果使用的是 360 安全浏览器,发现会出现域名重定向的提示:
查看 http 请求和响应信息:
状态码为 301,跳转后的网址 Location: http://www.lamper.com,L 表示 last,意思是跳转一次就结束。
注意:
域名重定向最常用到的是 301 和 302 这两个 http 状态码,301 重定向和 302 重定向的区别:
301 重定向是永久的重定向,搜索引擎在抓取新的内容的同时也将旧的网址替换为了重定向之后的网址。
302重定向只是临时的重定向,搜索引擎会抓取新的内容而保留旧的地址,因为服务器返回 302,所以,搜索搜索引擎认为新的网址是暂时的。302 又叫 redirect。
2.4 配置访问日志
系统的访问日志可以记录网站的访问情况,还可以在网站出现异常发生时帮助我们定位问题。
要配置 httpd 的访问日志,首先需要在主配置文件中定义访问日志的格式,打开 httpd 的主配置文件:
/usr/local/apache24/conf/httpd.conf
[root@ryan conf]# grep -i LogFormat /usr/local/apache24/conf/httpd.conf
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
可以看到httpd已经提供了两种格式,combined 和common 分别相当于对应格式的引用名称,当让也可以自定义日志格式和引用名称。要使用第三种格式 combinedio,则必须启用 mod_logio.c 模块。
参数说明:
%a 远端IP地址
%A 本机IP地址
%B 除HTTP头以外传送的字节数
%b 以CLF格式显示的除HTTP头以外传送的字节数,也就是当没有字节传送时显示’-'而不是0。
%{Foobar}C 在请求中传送给服务端的cookieFoobar的内容。
%D 服务器处理本请求所用时间,以微为单位。
%{FOOBAR}e 环境变量FOOBAR的值
%f 文件名
%h 远端主机
%H 请求使用的协议
%{Foobar}i 发送到服务器的请求头Foobar:的内容。
%l 远端登录名(由identd而来,如果支持的话),除非IdentityCheck设为"On",否则将得到一个"-"。
%m 请求的方法
%{Foobar}n 来自另一个模块的注解Foobar的内容。
%{Foobar}o 应答头Foobar:的内容。
%p 服务器服务于该请求的标准端口。
%P 为本请求提供服务的子进程的PID。
%{format}P 服务于该请求的PID或TID(线程ID),format的取值范围为:pid和tid(2.0.46及以后版本)以及hextid(需要APR1..0及以上版本)
%q 查询字符串(若存在则由一个"?"引导,否则返回空串)
%r 请求的第一行
%s 状态。对于内部重定向的请求,这个状态指的是原始请求的状态,—%>s则指的是最后请求的状态。
%t 时间,用普通日志时间格式(标准英语格式)
%{format}t 时间,用strftime()指定的格式表示的时间。(默认情况下按本地化格式)
%T 处理完请求所花时间,以秒为单位。
%u 远程用户名(根据验证信息而来;如果返回status(%s)为401,可能是假的)
%U 请求的URL路径,不包含查询字符串。
%v 对该请求提供服务的标准ServerName。
%V 根据UseCanonicalName指令设定的服务器名称。
%X 请求完成时的连接状态:X= 连接在应答完成前中断。
+= 应答传送完后继续保持连接。
-= 应答传送完后关闭连接。 (在1.3以后的版本中,这个指令是%c,但这样就和过去的SSL语法:%{var}c冲突了)
%I 接收的字节数,包括请求头的数据,并且不能为零。要使用这个指令你必须启用mod_logio模块。
%O 发送的字节数,包括请求头的数据,并且不能为零。要使用这个指令你必须启用mod_logio模块。 修饰符
可以紧跟在"%"后面加上一个逗号分隔的状态码列表来限制记录的条目。例如,"%400,501{User-agent}i" 只记录状态码400和501发生时的User-agent头内容;不满足条件时用"-"代替。状态码前还可以加上"!"前缀表示否 定,"%!200,304,302{Referer}i"记录所有不同于200,,302的状态码发生时的Referer头内容。 "<"和">"修饰符可以用来指定对于已被内部重定向的请求是选择原始的请求还是选择最终的请求。默认情况下,%s, %U, %T, %D, %r 使用原始请求,而所有其他格式串则选择最终请求。例如,%>s 可以用于记录请求的最终状态,而 %<u 则记录一个已经被内部重定向到非认证资源的请求的原始认证用户。
继续编辑虚拟主机配置文件
/usr/local/apache24/conf/extra/httpd-vhosts.conf
[root@ryan conf]# vim /usr/local/apache24/conf/extra/httpd-vhosts.conf
<VirtualHost *:>
#ServerAdmin webmaster@dummy-host.example.com
DocumentRoot "/data/www/DiscuzX"
ServerName www.lamper.com
ServerAlias lamper.com
ErrorLog "logs/www.lamper.com-error_log"
CustomLog "logs/www.lamper.com-access_log" combined
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www.amlinux.com$
RewriteRule ^/(.*)$ http://www.lamper.com/$1 [R=301,L]
</IfModule>
<Directory "/data/www/DiscuzX/admin.php">
AllowOverride AuthConfig
AuthName "lamper.com user auth"
AuthType Basic
AuthUserFile /data/.htpasswd
require valid-user
</Directory>
</VirtualHost>
我们将系统默认的 common 格式修改为 combined,这样记录的信息会更全面一些。
保存之后,我们验证一下:
[root@ryan conf]# /usr/local/apache24/bin/apachectl -t
Syntax OK
[root@ryan conf]# /usr/local/apache24/bin/apachectl graceful
[root@ryan conf]# curl -x127.0.0.: -I www.lamper.com
HTTP/1.1 OK
Date: Sat, Jul :: GMT
Server: Apache/2.4. (Unix) PHP/7.2.
X-Powered-By: PHP/7.2.
Set-Cookie: P6bY_2132_saltkey=ZCE7eKcE; expires=Mon, -Aug- :: GMT; Max-Age=; path=/; HttpOnly
Set-Cookie: P6bY_2132_lastvisit=; expires=Mon, -Aug- :: GMT; Max-Age=; path=/
Set-Cookie: P6bY_2132_sid=PCAWeC; expires=Sun, -Jul- :: GMT; Max-Age=; path=/
Set-Cookie: P6bY_2132_lastact=%09index.php%; expires=Sun, -Jul- :: GMT; Max-Age=; path=/
Set-Cookie: P6bY_2132_onlineusernum=; expires=Sat, -Jul- :: GMT; Max-Age=; path=/
Set-Cookie: P6bY_2132_sid=PCAWeC; expires=Sun, -Jul- :: GMT; Max-Age=; path=/
Content-Type: text/html; charset=utf- [root@ryan conf]# tail /usr/local/apache24/logs/www.lamper.com-access_log
192.168.1.101 - - [/Jul/::: +] "GET /static/image/admincp/btn_block.gif HTTP/1.1"
192.168.1.101 - - [/Jul/::: +] "GET /static/image/admincp/logo.gif HTTP/1.1"
192.168.1.101 - - [/Jul/::: +] "GET /static/image/admincp/bg_repx_h.gif HTTP/1.1"
192.168.1.101 - admin [/Jul/::: +] "GET /admin.php?action=index HTTP/1.1"
192.168.1.101 - - [/Jul/::: +] "GET /static/image/admincp/logo_hover.gif HTTP/1.1"
192.168.1.101 - admin [/Jul/::: +] "GET /admin.php?action=setting&operation=basic HTTP/1.1"
192.168.1.101 - - [/Jul/::: +] "GET /static/image/admincp/bg_repx_hc.gif HTTP/1.1"
192.168.1.101 - admin [/Jul/::: +] "GET /admin.php?action=nav HTTP/1.1"
192.168.1.101 - - [/Jul/::: +] "GET /static/image/admincp/btn_block_3.gif HTTP/1.1"
127.0.0.1 - - [/Jul/::: +] "HEAD http://www.lamper.com/ HTTP/1.1" - "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
可以发现最后一行的日志信息是修改日志格式后产生的。
curl 命令
curl 命令可以用来执行下载、发送各种HTTP请求,指定 HTTP 头部等操作。如果系统没有 curl 可以使用 yum install curl 安装,也可以下载安装。curl 是将下载文件输出到 stdout,将进度信息输出到 stderr,不显示进度信息使用 --silent 选项。
上面使用到了 -x 选项可以为 CURL 添加代理功能,如:
# 指定代理主机和端口
curl -x proxysever.test.com: http://google.co.in
-I/--head 表示只显示请求头信息,如:
curl -I http://www.lamper.com
-e/--referer 表示来源网址,可以用来伪造 referer(盗链)
很多服务器会检查http访问的referer从而来控制访问。比如:你是先访问首页,然后再访问首页中的邮箱页面,这里访问邮箱的referer地址就是访问首页成功后的页面地址,如果服务器发现对邮箱页面访问的referer地址不是首页的地址,就断定那是个盗连了
curl 中内置 option:-e可以让我们设定referer,如下:
curl -e "http://www.amlinux.com" http://www.lamper.com
日志过滤掉静态文件
一个网站会有很多文件,其中就包括很多的图片、js、css 等静态文件,用户每请求一个页面就会访问这些静态元素,但是这些静态元素在日志里面存在的意义不大,为了防止日志文件过大,我们需要在记录日志时过滤掉这些静态文件,且需要敬日志按天归档,一天一个日志。
修改虚拟主机配置文件:/usr/local/apache24/conf/extra/httpd-vhosts.conf
[root@ryan conf]# vim /usr/local/apache24/conf/extra/httpd-vhosts.conf
<VirtualHost *:>
#ServerAdmin webmaster@dummy-host.example.com
DocumentRoot "/data/www/DiscuzX"
ServerName www.lamper.com
ServerAlias lamper.com
ErrorLog "logs/www.lamper.com-error_log"
SetEnvIf Request_URI ".*\.gif$" image-request
SetEnvIf Request_URI ".*\.jpg$" image-request
SetEnvIf Request_URI ".*\.png$" image-request
SetEnvIf Request_URI ".*\.bmp$" image-request
SetEnvIf Request_URI ".*\.swf$" image-request
SetEnvIf Request_URI ".*\.js$" image-request
SetEnvIf Request_URI ".*\.css$" image-request
CustomLog "logs/www.lamper.com-access_log" combined env=!image-request
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www.amlinux.com$
RewriteRule ^/(.*)$ http://www.lamper.com/$1 [R=301,L]
</IfModule>
<Directory "/data/www/DiscuzX/admin.php">
AllowOverride AuthConfig
AuthName "lamper.com user auth"
AuthType Basic
AuthUserFile /data/.htpasswd
require valid-user
</Directory>
</VirtualHost>
如上,先添加一个 image-request 环境变量,把 gif、jpg、png、bmp、swf、js 和 css 等格式的文件全部归类到 image-request 里,后面的 env=!image-request 用到了一个 "!" 表示取反,意思是只将 image-requset 以外的类型文件记录到日志里。
如果想将日志按天归档,可修改 CustomLog 为:
CustomLog "|/usr/local/apache24/bin/rotatelogs -l logs/www.lamper.com-access_%Y%m%d.log 86400" combined env=!image-request
正常 CustomLog 后面为日志文件名,但是这里使用一个管道,它会把日志内容交给后面的 rotatelogs(apache 自带的日志切割工具)命令处理,它会把访问日志按照我们定义的文件名进行切割,86400 单位为秒,相当于一天。
保存之后验证日志:
[root@ryan conf]# /usr/local/apache24/bin/apachectl -t
Syntax OK
[root@ryan conf]# /usr/local/apache24/bin/apachectl graceful
[root@ryan conf]# curl -x127.0.0.: -I www.lamper.com
HTTP/1.1 OK
Date: Sat, Jul :: GMT
Server: Apache/2.4. (Unix) PHP/7.2.
X-Powered-By: PHP/7.2.
Set-Cookie: P6bY_2132_saltkey=o77ZVSKV; expires=Mon, -Aug- :: GMT; Max-Age=; path=/; HttpOnly
Set-Cookie: P6bY_2132_lastvisit=; expires=Mon, -Aug- :: GMT; Max-Age=; path=/
Set-Cookie: P6bY_2132_sid=jWISSI; expires=Sun, -Jul- :: GMT; Max-Age=; path=/
Set-Cookie: P6bY_2132_lastact=%09index.php%; expires=Sun, -Jul- :: GMT; Max-Age=; path=/
Set-Cookie: P6bY_2132_onlineusernum=; expires=Sat, -Jul- :: GMT; Max-Age=; path=/
Set-Cookie: P6bY_2132_sid=jWISSI; expires=Sun, -Jul- :: GMT; Max-Age=; path=/
Content-Type: text/html; charset=utf- [root@ryan conf]# ll /usr/local/apache24/logs
total
-rw-r--r-- root root Jul : access_log
-rw-r--r-- root root Jul : error_log
-rw-r--r-- root root Jul : httpd.pid
-rw-r--r-- root root Jul : www.lamper.com-access_20180728.log
-rw-r--r-- root root Jul : www.lamper.com-access_log
-rw-r--r-- root root Jul : www.lamper.com-error_log
可以看到新生成的日志已经带了日期戳:www.lamper.com-access_20180728.log,而且以后会每天生成一个按日期命名的日志文件。我们可以再添加一个定时任务,将日期间隔大于两个月的日志,定期清理掉,达到释放磁盘的目的。
再来验证静态文件是否已经过滤:
[root@ryan conf]# touch /data/www/DiscuzX/ryan.jpg
[root@ryan conf]# touch /data/www/DiscuzX/ryan.txt
[root@ryan conf]# curl -x127.0.0.: www.lamper.com/ryan.jpg
[root@ryan conf]# curl -x127.0.0.: www.lamper.com/ryan.txt
[root@ryan conf]# cat /usr/local/apache24/logs/www.lamper.com-access_20180728.log
127.0.0.1 - - [/Jul/::: +] "HEAD http://www.lamper.com/ HTTP/1.1" - "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
127.0.0.1 - - [/Jul/::: +] "GET http://www.lamper.com/ryan.txt HTTP/1.1" - "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.21 Basic ECC zlib/1.2.3 libidn/1.18 libssh2/1.4.2"
在日志中只能看到请求 ryan.txt的日志记录,而看不到请求ryan.jpg的请求日志,表示日志已经过滤掉了静态元素。
2.5 配置静态元素过期时间
如果我们仔细查看日志文件,会发现存在状态码为304的日志记录,这个状态码表示该文件已经缓存到了用户的电脑里了,再次请求服务器的时候,不再下载,而是直接从用户的电脑缓存里面读取。这样可以提升用户访问网站的速度,且降低服务器的资源消耗。
如果服务器上面某个图片已经更改,那就需要访问新的图片,这就涉及到静态文件缓存时长的问题,也称作 "缓存过期时间"。
配置缓存过期时间需要使用到 mod_expires 模块,首先检查当前 httpd 是否支持 expires 模块:
[root@ryan conf]# /usr/local/apache24/bin/apachectl -M|grep -i expires
没有任何输出表示当前httpd并不支持expires模块,需要手动开启,如下:
[root@ryan conf]# vim /usr/local/apache24/conf/httpd.conf
//去掉前面的#注释,开启 expires 模块
LoadModule expires_module modules/mod_expires.so
[root@ryan conf]# /usr/local/apache24/bin/apachectl graceful
[root@ryan conf]# /usr/local/apache24/bin/apachectl -M|grep -i expires
expires_module (shared)
有上面的输出,表示已经正确加载了 expires 模块。
打开虚拟主机配置文件:/usr/local/apache24/conf/extra/httpd-vhosts.conf
[root@ryan conf]# vim /usr/local/apache24/conf/extra/httpd-vhosts.conf
<IfModule mod_expires.c>
ExpiresActive on
ExpiresByType image/gif "access plus 1 days"
ExpiresByType image/jpeg "access plus 24 hours"
ExpiresByType image/png "access plus 24 hours"
ExpiresByType text/css "now plus 2 hours"
ExpiresByType application/x-javascript "now plus 2 hours"
ExpiresByType application/x-shockwave-flash "now plus 2 hours"
ExpiresDefault "now plus 0 min"
</IfModule>
说明:
ExpiresActive on 表示开启过期时间功能。"access plus 1 days" 意指浏览时起算1天。依照 Apache 官方说明文件,过期起算时间有三种,分别是 access、now 以及 modification。其中 access 与 now 意义相同,而 modification 指的是网页文件的 "最后编辑时间"。所以如果要以文档的最后编辑时间起算,可以写成这样:"modification plus 1 days"。而时间的指定也很简单,就是英文单词(years、months、weeks、days、hours、minutes、seconds)。例如,可以写成这样:"access plus 1 month 15 days 2 hours"。
验证元素过期时间
[root@ryan conf]# curl -x127.0.0.: -I 'http://www.lamper.com/static/image/common/logo.png'
HTTP/1.1 OK
Date: Sat, Jul :: GMT
Server: Apache/2.4. (Unix) PHP/7.2.
Last-Modified: Mon, Jun :: GMT
ETag: "1149-56dce3b2c41c0"
Accept-Ranges: bytes
Content-Length:
Content-Type: image/png [root@ryan conf]# /usr/local/apache24/bin/apachectl -t
Syntax OK
[root@ryan conf]# /usr/local/apache24/bin/apachectl graceful
[root@ryan conf]# curl -x127.0.0.: -I 'http://www.lamper.com/static/image/common/logo.png'
HTTP/1.1 OK
Date: Sat, Jul :: GMT
Server: Apache/2.4. (Unix) PHP/7.2.
Last-Modified: Mon, Jun :: GMT
ETag: "1149-56dce3b2c41c0"
Accept-Ranges: bytes
Content-Length:
Cache-Control: max-age=86400
Expires: Sun, 29 Jul 2018 07:45:58 GMT
Content-Type: image/png
可以看到修改后比修改前多了 max-age 等头信息,同样,86400单位为秒,表示一天,与上面的设置: ExpiresByType image/png "access plus 24 hours" 保持一致,表示设置成功,通常可以设置过期日期为 30 天。
2.6 配置防盗链
通过防盗链的方式,可以设置限制第三方的站点通过引用的方式获取服务器上的图片,数据等,如果想要获取本站点的图片数据,只能通过本站点访问获取,这样也有效的减少了服务器的资源。
配置防盗链之前,需要了解什么是 referer?
HTTP Referer是 request header 的一部分,当浏览器向 web 服务器发送请求的时候,一般会带上 Referer,告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理。
比如:在A网站的某个页面 http://aaa.com/a.html 里面的链接去访问B网站的某个页面 http://bbb.com/b.html,那么 B 网站的 reffer 就是http://aaa.com/a.html。
编辑虚拟主机配置文件,添加防盗链规则:
[root@ryan conf]# vim /usr/local/apache24/conf/extra/httpd-vhosts.conf
<Directory "/data/www/DiscuzX">
SetEnvIfNoCase Referer "http://www.lamper.com" local_ref
SetEnvIfNoCase Referer "http://lamper.com" local_ref
SetEnvIfNoCase Referer "^$" local_ref
<FilesMatch "\.(txt|doc|mp3|zip|rar|jpg|gif|png)">
Order Allow,Deny
Allow from env=local_ref
</FilesMatch>
</Directory>
首先定义允许访问链接的 referer,其中 ^$ 为空 refer,当直接在浏览器中输入图片们地址去访问它时,他的 referer 就为空。然后使用 FileMatch 来定义需要保护的文件类型,访问 txt、doc、mp3、zip、rar、jpg、gif、png 等格式的文件,当访问这样类型的文件时就会运用防盗链规则。
验证防盗链
[root@ryan conf]# curl -x 127.0.0.1: -I -e "http://www.amlinux.com" http://www.lamper.com/static/image/common/logo.png
HTTP/1.1 OK
Date: Sat, Jul :: GMT
Server: Apache/2.4. (Unix) PHP/7.2.
Last-Modified: Mon, Jun :: GMT
ETag: "1149-56dce3b2c41c0"
Accept-Ranges: bytes
Content-Length:
Cache-Control: max-age=
Expires: Sun, Jul :: GMT
Content-Type: image/png [root@ryan conf]# /usr/local/apache24//bin/apachectl -t
Syntax OK
[root@ryan conf]# /usr/local/apache24//bin/apachectl graceful
[root@ryan conf]# curl -x 127.0.0.1: -I -e "http://www.amlinux.com" http://www.lamper.com/static/image/common/logo.png
HTTP/1.1 Forbidden
Date: Sat, Jul :: GMT
Server: Apache/2.4. (Unix) PHP/7.2.
Content-Type: text/html; charset=iso--
对比配置文件生效前后,请求同一个 png 图片的请求结果,发现已经生效,状态码 403 Forbidden,表示禁止访问某些资源。-e 来定义 referer,这个 referer 建议以 http:// 开头,否则可能导致不生效。
[root@ryan conf]# curl -x 127.0.0.1: -I -e "http://www.amlinux.com" http://www.lamper.com/rayn.jpg
HTTP/1.1 Forbidden
Date: Sat, Jul :: GMT
Server: Apache/2.4. (Unix) PHP/7.2.
Content-Type: text/html; charset=iso-- [root@ryan conf]# curl -x 127.0.0.1: -I -e "http://www.amlinux.com" http://www.lamper.com/rayn.txt
HTTP/1.1 Forbidden
Date: Sat, Jul :: GMT
Server: Apache/2.4. (Unix) PHP/7.2.
Content-Type: text/html; charset=iso-- [root@ryan conf]# touch /data/www/DiscuzX/rayn.html
[root@ryan conf]# curl -x 127.0.0.1: -I -e "http://www.amlinux.com" http://www.lamper.com/rayn.html
HTTP/1.1 OK
Date: Sat, Jul :: GMT
Server: Apache/2.4. (Unix) PHP/7.2.
Last-Modified: Sat, Jul :: GMT
ETag: "0-5720c04b33a19"
Accept-Ranges: bytes
Cache-Control: max-age=
Expires: Sat, Jul :: GMT
Content-Type: text/html
对于不是上面限制的格式,比如 .html,可以正常访问,没有运用防盗链规则。
2.7 访问控制
对于一些比较重要的网站内容,除了可以使用用户认证限制访问之外,还可以通过其他一些方法做到限制,比如可以限制 IP,也可以限制 user_agent。限制 IP 指的是限制访问网站的来源IP,而限制 user_agent,通常用来限制恶意或者不正常的请求。
一般凡是涉及网站后台的访问都要做 IP 限制,只允许公司内网IP或者被信任的公司IP访问。这样就可以防止别有用心的人拿到网站后台权限,并获得数据。
首先限制IP访问,编辑虚拟机主机配置文件,如下:
[root@ryan conf]# vim /usr/local/apache24/conf/extra/httpd-vhosts.conf
<Directory "/data/wwww/DiscuzX/admin/">
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Directory>
使用 <Directory> 来指定要限制访问的目录,Order 定义控制顺序,哪个在前面就先匹配哪个规则。本例中 deny 在前,所以先匹配 Deny from all,表示所有的IP都会被限制,然后匹配 Allow from 127.0.0.1,这样只允许127.0.0.1 这个 IP 访问目录: /data/wwww/DiscuzX/admin/,所以最终也只有 127.0.0.1 才能访问 /data/wwww/DiscuzX/admin/。
验证访问控制:
[root@ryan conf]# mkdir /data/www/DiscuzX/admin
[root@ryan conf]# echo "admin" > /data/www/DiscuzX/admin/index.html
[root@ryan conf]# curl -x 192.168.1.121: -I http://www.lamper.com/admin/index.html
HTTP/1.1 200 OK
Date: Sat, Jul :: GMT
Server: Apache/2.4. (Unix) PHP/7.2.
Last-Modified: Sat, Jul :: GMT
ETag: "6-5720d737d5bf5"
Accept-Ranges: bytes
Content-Length:
Cache-Control: max-age=
Expires: Sat, Jul :: GMT
Content-Type: text/html [root@ryan conf]# curl -x 127.0.0.1: -I http://www.lamper.com/admin/index.html
HTTP/1.1 OK
Date: Sat, Jul :: GMT
Server: Apache/2.4. (Unix) PHP/7.2.
Last-Modified: Sat, Jul :: GMT
ETag: "6-5720d737d5bf5"
Accept-Ranges: bytes
Content-Length:
Cache-Control: max-age=
Expires: Sat, Jul :: GMT
Content-Type: text/html [root@ryan conf]# /usr/local/apache24/bin/apachectl -t
Syntax OK
[root@ryan conf]# /usr/local/apache24/bin/apachectl graceful
[root@ryan conf]# curl -x 192.168.1.121: -I http://www.lamper.com/admin/index.html
HTTP/1.1 OK
Date: Sat, Jul :: GMT
Server: Apache/2.4. (Unix) PHP/7.2.
Last-Modified: Sat, Jul :: GMT
ETag: "6-5720d737d5bf5"
Accept-Ranges: bytes
Content-Length:
Cache-Control: max-age=
Expires: Sat, Jul :: GMT
Content-Type: text/html [root@ryan conf]# curl -x 127.0.0.1: -I http://www.lamper.com/admin/index.html
HTTP/1.1 OK
Date: Sat, Jul :: GMT
Server: Apache/2.4. (Unix) PHP/7.2.
Last-Modified: Sat, Jul :: GMT
ETag: "6-5720d737d5bf5"
Accept-Ranges: bytes
Content-Length:
Cache-Control: max-age=
Expires: Sat, Jul :: GMT
Content-Type: text/html [root@ryan conf]# /usr/local/apache24/bin/apachectl -t
Syntax OK
[root@ryan conf]# /usr/local/apache24/bin/apachectl graceful
[root@ryan conf]# curl -x 192.168.1.121: -I http://www.lamper.com/admin/index.html
HTTP/1.1 403 Forbidden
Date: Sat, Jul :: GMT
Server: Apache/2.4. (Unix) PHP/7.2.
Content-Type: text/html; charset=iso-- [root@ryan conf]# curl -x 127.0.0.1: -I http://www.lamper.com/admin/index.html
HTTP/1.1 OK
Date: Sat, Jul :: GMT
Server: Apache/2.4. (Unix) PHP/7.2.
Last-Modified: Sat, Jul :: GMT
ETag: "6-5720d737d5bf5"
Accept-Ranges: bytes
Content-Length:
Cache-Control: max-age=
Expires: Sat, Jul :: GMT
Content-Type: text/html
修改前用 Windows 的浏览器访问:
修改后用 Windows 的浏览器访问:
也可以针对单个文件来做限制
<Directory "/data/www/DiscuzX">
<FilesMatch "admin.php(.*)">
Order Deny,Allow
Deny from all
Allow from 127.0.0.1
</FilesMatch>
</Directory>
禁止某些目录解析PHP代码
有些 PHP 网站运行上传文件,如果某些黑客上传了一个用PHP写的木马,由于网站可以执行PHP代码,这样就可能导致黑客拿到服务器权限,为了避免此类情况发送,我们需要把能上传文件的目录禁止解析 PHP代码。
编辑虚拟主机配置文件,如下:
#禁止解析某些目录的PHP代码
<Directory "/data/www/DiscuzX/upload/">
php_admin_flag engine off
</Directory>
验证过程如下:
[root@ryan conf]# mkdir /data/www/DiscuzX/upload
[root@ryan conf]# cp /usr/local/apache24/htdocs/test.php /data/www/DiscuzX/upload/
[root@ryan conf]# ll /data/www/DiscuzX/upload
total
-rw-r--r-- root root Jul : test.php
[root@ryan conf]# curl -x127.0.0.: www.lamper.com/upload/test.php
我的LAMP
[root@ryan conf]# /usr/local/apache24/bin/apachectl -t
Syntax OK
[root@ryan conf]# /usr/local/apache24/bin/apachectl graceful
[root@ryan conf]# curl -x127.0.0.: www.lamper.com/upload/test.php
<?php
echo "我的LAMP";
?>
说明 upload 目录下的 test.php 已经不能正常解析了。
限制 user_agent
user_agent 为浏览器标识,当我们用 Chrome 浏览器访问网站时,user_agent 为 "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",firefox 浏览器访问时的user_agent 为 "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0",IE 浏览器访问时的 user_agent 为 "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)",通常可以针对一些恶意网络爬虫来做 user_agent 限制。
修改虚拟主机配置文件,如下:
[root@ryan conf]# vim /usr/local/apache24/conf/extra/httpd-vhosts.conf
#限制某些USER_AGENT访问网站
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} .*Firefox.* [NC,OR]
RewriteCond %{HTTP_USER_AGENT} .*Chrome.* [NC]
RewriteRule .* - [F]
</IfModule>
这里也使用到了 rewrite 模块,%{HTTP_USER_AGENT} 为user_agent 的内置变量,NC表示不区分大小写,OR表示或者,F相当于Forbidden,此例中,限制火狐 Firefox 和谷歌 Chrome 浏览器访问本网站。
使配置生效
[root@ryan conf]# /usr/local/apache24/bin/apachectl -t
Syntax OK
[root@ryan conf]# /usr/local/apache24/bin/apachectl graceful
验证
Firefox 浏览器:
Chorome 浏览器:
IE 浏览器:
发现 Firefox 和 Chrome 浏览器已经被限制访问了。
三、PHP 配置
虽然 PHP 是以 httpd 一个模块的形式存在的,但是 PHP 本身也有自己的配置文件。查看 PHP 配置文件所在位置的命令:
[root@ryan ~]# /usr/local/php7/bin/php -i |grep -i configuration
Configuration File (php.ini) Path => /usr/local/php7/etc
Loaded Configuration File => /usr/local/php7/etc/php.ini
Configuration
php.ini 为 PHP 的配置文件,可以看出其在 /usr/local/php7/etc/php.ini,比如可以设置时区为:
[root@ryan ~]# fgrep date.timezone /usr/local/php7/etc/php.ini
; http://php.net/date.timezone
;date.timezone = Asia/Shanghai
分号;在 php.ini 中表示注释。
3.1 配置 PHP 的 disable_functions
PHP 有很多的内置函数,有一些函数会直接调用Linux系统命令,如果开放此函数的话将会带来很大的危险。因此,基于风险考虑,可以将这些不安全的函数禁掉。如下:
[root@ryan ~]# vim /usr/local/php7/etc/php.ini
disable_functions = phpinfo,eval,passthru,exec,system,chroot,scandir,chgrp,chown,shell_exec,proc_open,proc_get_status,ini_alter,ini_alter,ini_restore,dl,pfsockopen,openlog,syslog,readlink,symlink,popepassthru,stream_socket_server,fsocket,fsockopen
这些被禁掉的函数是不能在PHP代码中调用的。更改完php.ini后,由于需要在httpd中调用PHP,所以还需要重启httpd服务使其生效。
比如在网站根目录下新建一个phpinfo.php文件,添加如下内容:
<?php
phpinfo();
?>
然后访问:http://www.lamper.com/phpinfo.php,保存前发现可以正常访问,保存后再次访问时发现是 "白屏"。
[root@ryan ~]# tail /usr/local/apache24/logs/www.lamper.com-error_log
[Sun Jul ::54.458570 ] [php7:warn] [pid :tid ] [client 127.0.0.1:] PHP Warning: phpinfo() has been disabled for security reasons in /data/www/DiscuzX/phpinfo.php on line
查看日志发现给出了提示:phpinfo() has been disabled for security reasons in /data/www/DiscuzX/phpinfo.php on line 2
3.2 配置 error_log
PHP的日志对于程序员来说非常重要,通过它可以排查好多问题。
设置如下:
[root@ryan ~]# vim /usr/local//php7/etc/php.ini
log_errors = On
error_log = /var/log/php7/php_errors.log
error_reporting = E_ALL & ~E_NOTICE
display_errors = Off
说明:log_errors 可以设置为 on 或者 off,如果想让 PHP 记录错误日志,需要设置为 on。error_log 设定错误日志路径。error_reporting 设定错误日志的级别,E_ALL 为所有类型的日志,不管是提醒还是警告都会记录。在开发环境下面设置为 E_ALL,可以方便开发人员排查问题,&表示并且,~表示排除,所以两者组合在一起使用时,就表示在E_ALL的基础上排除掉notice相关的日志。display_errors 设置为 on,则会把错误信息直接显示在浏览器的页面中,这样对用户来说不友好,而且还会暴露网站的一些文件的路径等信息,所以将其设置为 off。
[root@ryan ~]# mkdir /var/log/php7
[root@ryan ~]# chmod /var/log/php7
[root@ryan ~]# apachectl graceful
需要手动创建日志目录,并且权限可写。
3.3 配置 open_basedir
open_basedir 的作用是将网站限定在指定目录里,就算该站点被黑了,黑客也只能在该目录下面操作,而不能操作其他目录。如果你的服务器上只有一个站点,那可以直接在 php.ini 中设置 open_basedir 参数。但如果服务器上跑的站点比较多,那在 php.ini 中设置就不合适了,因为在php.ini中只能定义一次,也就是所所有站点都一起定义限定的目录,那这样似乎起不到隔离多个站点的目的,此时可以将其定义在虚拟主机的配置文件中。
先来在 php.ini 中配置 open_basedir,如下:
[root@ryan ~]# vim /usr/local//php7/etc/php.ini
open_basedir = /data/www/DiscuzX:/tmp
open_basedir 可以是多个目录,之间用:分隔。
也可以在虚拟主机配置文件中设置,如下:
[root@ryan ~]# vim /usr/local/apache24/conf/extra/httpd-vhosts.conf
php_admin_value open_basedir "/data/www/DiscuzX/:/tmp/"
可以将 php_admin_value 这一行添加到 CustomLog 这一行下面。
附录
关于USER_AGENT:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/User-Agent
Php与Apache的三种结合方式以及各自优缺点:https://blog.csdn.net/sinat_22991367/article/details/73431316
Linux 笔记 - 第十四章 LAMP 之(二) 环境配置的更多相关文章
- Linux 笔记 - 第十四章 LAMP 之(一) 环境搭建
博客地址:http://www.moonxy.com 一.前言 LAMP 是 Linux Apache MySQL PHP 的简写,即把 Apache.MySQL 以及 PHP 安装在 Linux 系 ...
- Linux 笔记 - 第二十四章 配置 Tomcat
一.前言 Tomcat 是 Apache 软件基金会(Apache Software Foundation)Jakarta 项目中的核心项目,由 Apache.Sun 和其他一些公司及个人共同开发.使 ...
- Linux 笔记 - 第十九章 配置 Squid 正向代理和反向代理服务
一.简介 Squid 是一个高性能的代理缓存服务器,对应中文的乌贼,鱿鱼的意思.Squid 支持 FTP,gopher 和 HTTP 协议.和一般的代理缓存软件不同,Squid 用一个单独的,非模块化 ...
- 《linux程序设计》--读书笔记--第十四章信号量、共享内存和消息队列
信号量:用于管理对资源的访问: 共享内存:用于在程序之间高效的共享数据: 消息队列:在程序之间传递数据的一种简单方法: 一.信号量 临界代码:需要确保只有一个进程或者一个执行线程可以进入这个临界代码并 ...
- 《机器学习实战》学习笔记第十四章 —— 利用SVD简化数据
相关博客: 吴恩达机器学习笔记(八) —— 降维与主成分分析法(PCA) <机器学习实战>学习笔记第十三章 —— 利用PCA来简化数据 奇异值分解(SVD)原理与在降维中的应用 机器学习( ...
- Linux 笔记 - 第十六章 LNMP 之(一) 环境搭建
博客地址:http://www.moonxy.com 一.前言 LNMP 中的 N 指 Nginx,在静态页面的处理上,Nginx 较 Apache 更胜一筹:但在动态页面的处理上,Nginx 并不比 ...
- Linux 笔记 - 第十五章 MySQL 常用操作和 phpMyAdmin
博客地址:http://www.moonxy.com 一.前言 前面几章介绍了 MySQL 的安装和简单的配置,只会这些还不够,作为 Linux 系统管理员,我们还需要掌握一些基本的操作,以满足日常管 ...
- C primer plus 读书笔记第十四章
这一章主要介绍C语言的结构和其他数据形式,是学习算法和数据结构的重点. 1.示例代码 /*book.c -- 仅包含一本书的图书目录*/ #include <stdio.h> #defin ...
- 学习笔记 第十四章 使用CSS3动画
第14章 使用CSS3动画 [学习重点] 设计2D动画 设计3D动画 设计过渡动画 设计帧动画 能够使用CSS3动画功能设计页面特效样式 14.1 设计2D动画 CSS2D Transform表 ...
随机推荐
- Mina各组件介绍
Mina各组件介绍 上一篇文章已经系统的介绍了Mina的运行流程,Apache推出的Mina性能上很是高效,上章节我们知道内部有很多的类,各个类之间的依赖也是很多,他们之家都是相互依赖. 下面主要看看 ...
- vue路由传参的三种方式以及解决vue路由传参页面刷新参数丢失问题
最近项目中涉及到跨页面传参数和后台进行数据交互,看到需求之后第一反应就是用路由传参来解决:Vue中给我们提供了三种路由传参方式,下面我们一个一个的来看一下: 方法一:params传参: this.$r ...
- 最小生成树详细讲解(一看就懂!) & kruskal算法
0.前言 因为本人太蒟了 我现在连NOIP的初赛都在胆战心惊 并且我甚至连最小生成树都没有学过 所以这一篇博客一定是最详细的QAQ 哈哈 请您认真看完如果有疏漏之处敬请留言指正 感谢! Thanks♪ ...
- mysql datetime timestamp区别
timestamp 支持数据库级UTC 时区 datetime 不支持 timestamp占4个字节 datetime占8个字节 timestamp所能存储的时间范围为:'1970-01-01 00 ...
- linux_密钥
使用密钥文件. 这里假设主机A(192.168.100.3)用来获到主机B(192.168.100.4)的文件. 在主机A上执行如下命令来生成配对密钥: ssh-keygen -t r ...
- $('div','li') 和 $('div , li') 和 $('div li') 区别
$('div','li')是$(子,父),是从父节点里找子,而不是找li外面的div $('div , li')才是找所有的div和li,之间不存在父子关系 $('div li') 是找div里面所有 ...
- C#中的扩展方法(向已有类添加方法,但无需创建新的派生类型)
C#中的扩展方法 扩展方法使你能够向现有类型"添加"方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样 ...
- 开发人员需要掌握的日常Linux命令集
本文整理了开发人员日常用到的linux相关命令,供参考. 文件相关 cd # 进入某个目录,不接参数进入当前用户目录(等同于cd ~)如/home/devuser,可接绝对路径或相对路径(../..表 ...
- PythonI/O进阶学习笔记_3.1面向对象编程_python的多态和鸭子类型
前言: 与第一篇的面向对象内容不同的是,第一篇中的面向对象更多的是与类.对象结合起来的概念粗浅理解,就是在编程历史中诞生的一种思想方法. 这篇的面向对象编程,更多落实到在语言设计实现中,是如何体现面向 ...
- 关于line-height 行高的一些理解和技巧
大家都知道,如何设置文字垂直居中,也就是:设置line-height 和 外围盒子的高度height一致: 其实这里有个地方,是多余的,也就是height,设不设置都居中: 那么,行高是生产高度的? ...