英国安全公司 Secarma 的研究主管 Sam Thomas 本月在 Black Hat 和 BSides 安全会议上展示了 PHP 编程语言的安全漏洞,并指出该漏洞影响了所有接受用户资料的 PHP 应用程序和库,包括 WordPress 等内容管理系统(CMS),并将允许远程程序攻击。 序列化(Serialization)与反序列化(Deserialization)是所有编程语言都具备的功能,序列化将对象转换为字符串,以将数据迁移到不同服务器,服务或应用程序上,然后通过反序列将字符串还原到对象。 安全研究员 Stefan Essar 在 2009 年就透露了 PHP 中反序列化黑客控制的数据带来的风险,而相关的漏洞不仅存在于 PHP 中,还存在于其他编程语言中。 Thomas 公布的是 PHP 的新攻击技术,可用于各种场景,例如 XML External Entity(XEE)漏洞或服务器端伪造请求(SSFR)漏洞等。 Thomas 表示,过去外界认为 XXE 漏洞带来的最大问题是信息外泄,但现在可出发程序执行。相关攻击分为两个阶段。 首先,将包含恶意对象的 Phar 存档上传到攻击目标的本地文件系统,然后触发一个基于 phar:// 的文件操作,就可能导致恶意程序执行。 Thomas 已利用 PHP 的反序列化程序成功攻击了 WordPress 与 Typo3 内容管理平台,以及 Contao 所采用的 TCPDF 库。 from:https://www.oschina.net/news/99165/php-unserialization-vulnerability
View Details前言: 1.少安装PHP模块, 费内存 2.调高linux内核打开文件数量,可以使用这些命令(必须是root帐号)(我是修改/etc/rc.local,加入ulimit -SHn 51200的)
1 2 3 |
echo `ulimit -HSn 65536` >> /etc/profile echo `ulimit -HSn 65536` >> /etc/rc.local source /etc/profile |
如果ulimit -n数量依旧不多(即上面配置没生效)的话, 可以在 /etc/security/limits.conf 文件最后加上
1 2 |
* soft nofile 51200 * hard nofile 51200 |
1.与Nginx使用Unix域Socket通信(Nginx和php-fpm在同一台服务器) Unix域Socket因为不走网络,的确可以提高Nginx和php-fpm通信的性能,但在高并发时会不稳定。 Nginx会频繁报错:connect() to unix:/dev/shm/php-fcgi.sock failed (11: Resource temporarily unavailable) while connecting to upstream 可以通过下面两种方式提高稳定性: 1)调高nginx和php-fpm中的backlog 配置方法为:在nginx配置文件中这个域名的server下,在listen 80后面添加default backlog=1024。 同时配置php-fpm.conf中的listen.backlog为1024,默认为128。 2)增加sock文件和php-fpm实例数 再新建一个sock文件,在Nginx中通过upstream模块将请求负载均衡到两个sock文件背后的两套php-fpm实例上。 2.php-fpm参数调优 pm = dynamic; 表示使用哪种进程数量管理方式 dynamic表示php-fpm进程数是动态的,最开始是pm.start_servers指定的数量,如果请求较多,则会自动增加,保证空闲的进程数不小于pm.min_spare_servers,如果进程数较多,也会进行相应清理,保证多余的进程数不多于pm.max_spare_servers static表示php-fpm进程数是静态的, 进程数自始至终都是pm.max_children指定的数量,不再增加或减少 pm.max_children = 300; 静态方式下开启的php-fpm进程数量 pm.start_servers = 20; 动态方式下的起始php-fpm进程数量 pm.min_spare_servers = 5; 动态方式下的最小php-fpm进程数量 pm.max_spare_servers = 35; 动态方式下的最大php-fpm进程数量 如果pm为static, 那么其实只有pm.max_children这个参数生效。系统会开启设置数量的php-fpm进程 如果pm为dynamic, 那么pm.max_children参数失效,后面3个参数生效。系统会在php-fpm运行开始的时候启动pm.start_servers个php-fpm进程,然后根据系统的需求动态在pm.min_spare_servers和pm.max_spare_servers之间调整php-fpm进程数 那么,对于我们的服务器,选择哪种pm方式比较好呢?事实上,跟Apache一样,运行的PHP程序在执行完成后,或多或少会有内存泄露的问题。这也是为什么开始的时候一个php-fpm进程只占用3M左右内存,运行一段时间后就会上升到20-30M的原因了。 对于内存大的服务器(比如8G以上)来说,指定静态的max_children实际上更为妥当,因为这样不需要进行额外的进程数目控制,会提高效率。因为频繁开关php-fpm进程也会有时滞,所以内存够大的情况下开静态效果会更好。数量也可以根据 内存/30M 得到,比如8GB内存可以设置为100,那么php-fpm耗费的内存就能控制在 2G-3G的样子。如果内存稍微小点,比如1G,那么指定静态的进程数量更加有利于服务器的稳定。这样可以保证php-fpm只获取够用的内存,将不多的内存分配给其他应用去使用,会使系统的运行更加畅通。 对于小内存的服务器来说,比如256M内存的VPS,即使按照一个20M的内存量来算,10个php-cgi进程就将耗掉200M内存,那系统的崩溃就应该很正常了。因此应该尽量地控制php-fpm进程的数量,大体明确其他应用占用的内存后,给它指定一个静态的小数量,会让系统更加平稳一些。或者使用动态方式,因为动态方式会结束掉多余的进程,可以回收释放一些内存,所以推荐在内存较少的服务器或VPS上使用。具体最大数量根据 内存/20M 得到。比如说512M的VPS,建议pm.max_spare_servers设置为20。至于pm.min_spare_servers,则建议根据服务器的负载情况来设置,比较合适的值在5~10之间。 在4G内存的服务器上200就可以(我的1G测试机,开64个是最好的,建议使用压力测试获取最佳值) pm.max_requests = 10240; nginx php-fpm配置过程中最大问题是内泄漏出问题:服务器的负载不大,但是内存占用迅速增加,很快吃掉内存接着开始吃交换分区,系统很快挂掉!其实根据官方的介绍,php-cgi不存在内存泄漏,每个请求完成后php-cgi会回收内存,但是不会释放给操作系统,这样就会导致大量内存被php-cgi占用。 官方的解决办法是降低PHP_FCGI_MAX_REQUESTS的值,如果用的是php-fpm,对应的php-fpm.conf中的就是max_requests,该值的意思是发送多少个请求后会重启该线程,我们需要适当降低这个值,用以让php-fpm自动的释放内存,不是大部分网上说的51200等等,实际上还有另一个跟它有关联的值max_children,这个是每次php-fpm会建立多少个进程,这样实际上的内存消耗是max_children*max_requests*每个请求使用内存,根据这个我们可以预估一下内存的使用情况,就不用再写脚本去kill了。 request_terminate_timeout = 30; 最大执行时间, 在php.ini中也可以进行配置(max_execution_time) request_slowlog_timeout = 2; 开启慢日志 slowlog = log/$pool.log.slow; 慢日志路径 rlimit_files = 1024; 增加php-fpm打开文件描述符的限制 3.php-fpm的高CPU使用率排查方法 1)使用top命令, 直接执行top命令后,输入1就可以看到各个核心的CPU使用率。而且通过top […]
View Details注:laravel 查询返回行的都是 php 的 stdClass 对象实例,不是数组!!!! 1)查询多行(get)
1 |
DB::table('table_name')->get(); |
带偏移和限制的查询(skip take 或 offset limit)(两种用法是一样的)
1 2 3 4 5 |
//skip take DB::table('table_name')->skip(10)->take(10)->get(); //offset limit DB::table('table_name')->offset(20)->limit(10)->get(); |
2)查询一行(first)
1 |
DB::table('table_name')->first(); |
1 |
DB::table('table_name')->find(1); |
PS:find方法也可以查多行,它可以这样玩 DB::table('table_name')->find([1,2,3,4]); 3)直接查询一个字段(value)
1 |
DB::table('table_name')->where('name','Tiac')->value('email'); |
4)查询一列(pluck)
1 |
DB::table('table_name')->where('brand_id','100')->pluck('goods_id'); |
5)块组结果集(chunk) 使用情景: 假设我们需要查询 1 百万的数据,并对其做处理,一次性查询 1 百万并统一处理势必会对数据产生不小的压力,消耗大量的服务器资源,有没有一种更做优的处理方法? 将 1 百万的查询分成 1000 次 1000 条记录的查询的块查询怎样?? 这个 chunk的作用,chunk方法接口一个闭包函数做回调处理
1 2 3 4 5 |
DB::table('users')->orderBy('id')->chunk(1000, function($users) { foreach ($users as $user) { // } }); |
PS:上面只是举例,chunk 貌似不能和 limit 一起用,chunk 默认情况下一次性处理整张表的数据,不过我可以通过自己加判断用 return false 跳出 chunk 操作 6)聚合函数(count max min avg sum 等等)
1 |
DB::table('table_name')->count(); |
PS:其他聚合函数的使用方法一样的,不一一举例了 7)where 条件字句 这个比较多,懒得写了,想看的直接到 laravel 学院看吧,传送门:http://laravelacademy.org/post/6140.html#ipt_kb_toc_6140_8 (where, orWhere, whereNUll, whereIn, whereNotIn, whereBetween, whereNotBetween, whereDate, whereYear, whereMonth, whereDay 等等) 8)orderBy 排序字句
1 |
DB::table('table_name')->orderBy('id','desc')->get(); |
PS:如果想要返回随机的查询结果集,可以使用 inRandomOrder 子句 […]
View Details
1 2 3 4 |
$user_info = DB::table('usermetas') ->select('browser', DB::raw('count(*) as total')) ->groupBy('browser') ->get(); |
from:https://stackoverflow.com/questions/18533080/laravel-eloquent-groupby-and-also-return-count-of-each-group
View Details昨天在写程序的时候,发现在用户的时候记录IP和地区信息也许以后用得上,去网上找了找,发现实现的方式有好多好多,因为我用的ThinkPHP,后来又去TP官网找了找,最后采用了下面这种方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
<?php // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK IT ] // +---------------------------------------------------------------------- // | Copyright (c) 2009 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: liu21st <liu21st@gmail.com> // +---------------------------------------------------------------------- /** * IP 地理位置查询类 修改自 CoolCode.CN * 由于使用UTF8编码 如果使用纯真IP地址库的话 需要对返回结果进行编码转换 * @author liu21st <liu21st@gmail.com> */ class IpLocation { /** * QQWry.Dat文件指针 * * @var resource */ private $fp; /** * 第一条IP记录的偏移地址 * * @var int */ private $firstip; /** * 最后一条IP记录的偏移地址 * * @var int */ private $lastip; /** * IP记录的总条数(不包含版本信息记录) * * @var int */ private $totalip; /** * 构造函数,打开 QQWry.Dat 文件并初始化类中的信息 * * @param string $filename * @return IpLocation */ public function __construct($filename = "UTFWry.dat") { $this->fp = 0; if (($this->fp = fopen(dirname(__FILE__).'/'.$filename, 'rb')) !== false) { $this->firstip = $this->getlong(); $this->lastip = $this->getlong(); $this->totalip = ($this->lastip - $this->firstip) / 7; } } /** * 返回读取的长整型数 * * @access private * @return int */ private function getlong() { //将读取的little-endian编码的4个字节转化为长整型数 $result = unpack('Vlong', fread($this->fp, 4)); return $result['long']; } /** * 返回读取的3个字节的长整型数 * * @access private * @return int */ private function getlong3() { //将读取的little-endian编码的3个字节转化为长整型数 $result = unpack('Vlong', fread($this->fp, 3).chr(0)); return $result['long']; } /** * 返回压缩后可进行比较的IP地址 * * @access private * @param string $ip * @return string */ private function packip($ip) { // 将IP地址转化为长整型数,如果在PHP5中,IP地址错误,则返回False, // 这时intval将Flase转化为整数-1,之后压缩成big-endian编码的字符串 return pack('N', intval(ip2long($ip))); } /** * 返回读取的字符串 * * @access private * @param string $data * @return string */ private function getstring($data = "") { $char = fread($this->fp, 1); while (ord($char) > 0) { // 字符串按照C格式保存,以\0结束 $data .= $char; // 将读取的字符连接到给定字符串之后 $char = fread($this->fp, 1); } return $data; // return iconv('gb2312', 'utf-8', $data); //通用函数,不能在这转 } /** * 返回地区信息 * * @access private * @return string */ private function getarea() { $byte = fread($this->fp, 1); // 标志字节 switch (ord($byte)) { case 0: // 没有区域信息 $area = ""; break; case 1: case 2: // 标志字节为1或2,表示区域信息被重定向 fseek($this->fp, $this->getlong3()); $area = $this->getstring(); break; default: // 否则,表示区域信息没有被重定向 $area = $this->getstring($byte); break; } return $area; // return iconv('gb2312', 'utf-8', $area); //在最后统一转 } /** * 根据所给 IP 地址或域名返回所在地区信息 * * @access public * @param string $ip * @return array */ public function getlocation($ip='') { if (!$this->fp) return null; // 如果数据文件没有被正确打开,则直接返回空 if(empty($ip)) $ip = get_client_ip(); $location['ip'] = gethostbyname($ip); // 将输入的域名转化为IP地址 $ip = $this->packip($location['ip']); // 将输入的IP地址转化为可比较的IP地址 // 不合法的IP地址会被转化为255.255.255.255 // 对分搜索 $l = 0; // 搜索的下边界 $u = $this->totalip; // 搜索的上边界 $findip = $this->lastip; // 如果没有找到就返回最后一条IP记录(QQWry.Dat的版本信息) while ($l <= $u) { // 当上边界小于下边界时,查找失败 $i = floor(($l + $u) / 2); // 计算近似中间记录 fseek($this->fp, $this->firstip + $i * 7); $beginip = strrev(fread($this->fp, 4)); // 获取中间记录的开始IP地址 // strrev函数在这里的作用是将little-endian的压缩IP地址转化为big-endian的格式 // 以便用于比较,后面相同。 if ($ip < $beginip) { // 用户的IP小于中间记录的开始IP地址时 $u = $i - 1; // 将搜索的上边界修改为中间记录减一 } else { fseek($this->fp, $this->getlong3()); $endip = strrev(fread($this->fp, 4)); // 获取中间记录的结束IP地址 if ($ip > $endip) { // 用户的IP大于中间记录的结束IP地址时 $l = $i + 1; // 将搜索的下边界修改为中间记录加一 } else { // 用户的IP在中间记录的IP范围内时 $findip = $this->firstip + $i * 7; break; // 则表示找到结果,退出循环 } } } //获取查找到的IP地理位置信息 fseek($this->fp, $findip); $location['beginip'] = long2ip($this->getlong()); // 用户IP所在范围的开始地址 $offset = $this->getlong3(); fseek($this->fp, $offset); $location['endip'] = long2ip($this->getlong()); // 用户IP所在范围的结束地址 $byte = fread($this->fp, 1); // 标志字节 switch (ord($byte)) { case 1: // 标志字节为1,表示国家和区域信息都被同时重定向 $countryOffset = $this->getlong3(); // 重定向地址 fseek($this->fp, $countryOffset); $byte = fread($this->fp, 1); // 标志字节 switch (ord($byte)) { case 2: // 标志字节为2,表示国家信息又被重定向 fseek($this->fp, $this->getlong3()); $location['country'] = $this->getstring(); fseek($this->fp, $countryOffset + 4); $location['area'] = $this->getarea(); break; default: // 否则,表示国家信息没有被重定向 $location['country'] = $this->getstring($byte); $location['area'] = $this->getarea(); break; } break; case 2: // 标志字节为2,表示国家信息被重定向 fseek($this->fp, $this->getlong3()); $location['country'] = $this->getstring(); fseek($this->fp, $offset + 8); $location['area'] = $this->getarea(); break; default: // 否则,表示国家信息没有被重定向 $location['country'] = $this->getstring($byte); $location['area'] = $this->getarea(); break; } if (trim($location['country']) == 'CZ88.NET') { // CZ88.NET表示没有有效信息 $location['country'] = '未知'; } if (trim($location['area']) == 'CZ88.NET') { $location['area'] = ''; } $location['country']=iconv('gb2312', 'utf-8', $location['country']); $location['area']=iconv('gb2312', 'utf-8', $location['area']); return $location; } /** * 析构函数,用于在页面执行结束后自动关闭打开的文件。 * */ public function __destruct() { if ($this->fp) { fclose($this->fp); } $this->fp = 0; } } IpLocation.class.php |
这个是TP里带的,从上面的信息上来看已经很旧了,不过感觉写的还不错,就没改什么,只是在后面加上了
1 2 |
$location['country']=iconv('gb2312', 'utf-8', $location['country']); $location['area']=iconv('gb2312', 'utf-8', $location['area']); |
因为TP的纯真数据库已经转码了,但是很旧,似乎还是2012年的,IP这东西,那么老的东西估计很不准,于是我去纯真官网下了一个,但是纯真本身是GB2312的,所以要加上上面这两句转码一下。 然后在项目中导入了这个PHP类以后,这样去用就可以。
1 2 3 |
$ip=get_client_ip(); $ipData=new IpLocation("QQWry20140125.dat"); $ipInfo=$ipData->getlocation($ip); |
得到的结果是这样的,测试IP:218.197.147.154。
1 2 3 4 5 6 |
array (size=5) 'ip' => string '218.197.147.154' (length=15) 'beginip' => string '218.197.146.1' (length=13) 'endip' => string '218.197.147.154' (length=15) 'country' => string '湖北省武汉大学' (length=21) 'area' => string '外语自主学习中心' (length=24) |
最新版的纯真数据库去纯真官网下就可以,里面的QQWry.dat就是,用的时候也可以像我那样在后面标上版本,免得以后记不清。然后把.dat跟上面的php类放在一个目录下就OK啦。 from:https://www.cnblogs.com/fordawn/p/3538665.html
View Details一、问题描述 在apache2的httpd配置中,很多情况都会出现403。 刚安装好httpd服务,当然是不会有403的问题了。主要是修改了一些配置后出现,问题描述如下: 修改了DocumentRoot目录指向后,站点出现403错误。 设置了虚拟主机目录也可能导致403。 apache的httpd服务成功启动,看起来都很正常,却没有权限访问 日志出现: access to / denied (filesystem path '/srv/lxyproject/wsgi/django.wsgi') because search permissions are missing on a component of the path 设置虚拟目录后,错误日志出现:client denied by server configuration: /srv/lxyproject/wsgi/django.wsgi 二、分析问题及方案 下面一步步解决问题时注意错误日志内容。ok,开始。 1、httpd.conf中目录配置文件 如果显示更改了DocumentRoot,比如改为 "/usr/local/site/test" 。site目录和test目录是通过使用mkdir建立的,然后在test目录下放一个index.html。这种情况应该查看httpd.conf中配置。 你的<Directory "/usr/local/site/test">一定要和DocumentRoot一致,因为这段Directory是apache对该目录访问权限的设置,只有设置正确的目录,DocumentRoot才会生效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<Directory "/usr/local/site/test"> # # Possible values for the Options directive are "None", "All", # or any combination of: # Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews # # Note that "MultiViews" must be named *explicitly* --- "Options All" # doesn't give it to you. # # The Options directive is both complicated and important. Please see # http://httpd.apache.org/docs/2.4/mod/core.html#options # for more information. # Options Indexes FollowSymLinks # # AllowOverride controls what directives may be placed in .htaccess files. # It can be "All", "None", or any combination of the keywords: # Options FileInfo AuthConfig Limit # AllowOverride None # # Controls who can get stuff from this server. # Require all granted </Directory> |
2、目录访问权限 第一步配置正确还是出现403,检查目录配置<Directory "/usr/local/site/test">中是否有Deny from all。有则所有访问都会被拒绝,当然403了。 可以设置为Allow from all或者Require all granted来处理。 不要修改<Directory />根目录中Deny from all。 3、目录权限 如果至此还是403,可能是网站目录的权限问题。 apache要求目录具有执行权限,也就是x,要注意的是,你的目录树都应该拥有这些权限。 假如你的目录是/usr/local/site/test,那么要保证/usr,/usr/local,/usr/local/site,/usr/local/site/test这四个层级的目录都是755权限。
1 2 |
#chmod 755 /usr/local/site #chmod 755 /usr/local/site/test |
我犯过一个错就是只设置了最后一级目录权限,没有设置上级目录权限,导致403。 4、 虚拟目录 【这个问题我没遇到过,因为我没这样写过,网上资料这么写,可作为参考】 如果设置的是虚拟目录,那么你需要在httpd.conf中定义一个虚拟目录,而且像极了如下的片段:
1 2 3 4 5 6 7 8 9 |
Alias /<strong>folder </strong>"/usr/local/<strong>folder</strong>" <Directory "/usr/local/<strong>folder</strong>"> Options FollowSymLinks AllowOverride None Order deny,allow Deny from all Allow from 127.0.0.1 192.168.1.1 </Directory> |
如果是这一种情况,而且你写得类似我上面的代码,三处folder都是一样一样的,那绝对会是403!怎么解决呢,就是把跟在Alias后面斜杠后面的那串改了,改成什么,不要和虚拟目录的文件夹同名就好,然后我就可以用改过后的虚拟目录访问了,当然,改文件夹也行,只要你不怕麻烦,只要Alias后面的虚拟目录定义字符(红色)和实际文件夹名(黑色)不相同就OK。 5、selinux的问题 如果依然是403,那就是selinux在作怪了,于是,你可以把你的目录进行一下selinux权限设置。 今天我遇到的就是这个问题了。
1 2 |
#chcon -R -t httpd_sys_content_t /usr/local/site #chcon -R -t httpd_sys_content_t /usr/local/site/test |
网上资料说不过,这一步大多不会发生。但我的问题确实是,可能跟系统有关,具体原理还不是很懂。 6、wsgi的问题 我的虚拟主机配置为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<VirtualHost *:80> WSGIScriptAlias / /srv/lxyproject/wsgi/django.wsgi Alias /static/ /srv/lxyproject/collectedstatic/ ServerName 10.1.101.31 #ServerName example.com #ServerAlias www.example.com <Directory /srv/lxyproject/collectedstatic> Options Indexes FollowSymLinks AllowOverride None Require all granted </Directory> <Directory /srv/lxyproject/wsgi/> Allow from all </Directory> ErrorLog /etc/httpd/logs/lxyproject.error.log LogLevel warn </VirtualHost> |
我访问 log报错:
1 |
client denied by server configuration: /srv/lxyproject/wsgi/django.wsgi |
解决办法: 修改<Directory /srv/lxyproject/wsgi/>中Allow from all为:Require all granted。 这个问题是因为版本的原因, 我的httpd版本为:
1 2 3 4 |
[root@yl-web conf.d]# rpm -qa |grep httpd httpd-devel-2.4.6-31.el7.centos.x86_64 httpd-tools-2.4.6-31.el7.centos.x86_64 httpd-2.4.6-31.el7.centos.x86_64 |
而2.3以下版本用Allow from all,2.3及以上版本为Require all granted。
1 2 3 4 5 6 7 8 9 |
<Directory /home/aettool/aet/apache> <IfVersion < 2.3 > Order allow,deny Allow from all </IfVersion> <IfVersion >= 2.3> Require all granted </IfVersion> </Directory> |
[…]
View DetailsApache结合mod_dav_svn和mod_authz_svn打造SVN服务器 制作SVN服务器的软件和工具有很多,比如每个SVN都有的svnserve,以及图形化界面超容易使用的VisualSVN Server。但是,现在既然有Apache服务器,那就直接用就是了,而且还可以使用Web浏览目录。 首先,前往这里下载对应的SVN发行包,我下载的是Win32Svn。里面自带mod_dav_svn.so与mod_authz_svn.so。使用与Apache2.2,其他版本请自行测试。 然后,把Win32Svn解压缩,如d:\Subversion,然后在系统环境变量中加上d:\Subversion。 接着,把mod_dav_svn.so与mod_authz_svn.so拷贝到apache的modules目录。 修改httpd.conf,把以下两行前面的“#”注释去掉: LoadModule dav_fs_module modules/mod_dav_fs.so LoadModule dav_module modules/mod_dav.so 在所有LoadModule的最后加上下面两行: LoadModule dav_svn_module modules/mod_dav_svn.so LoadModule authz_svn_module modules/mod_authz_svn.so 假设使用d:\svn作为仓库的地址,则在httpd.conf或对应虚拟主机的配置中加上: #SVN START <Location /svn> DAV svn SVNParentPath D:\svn AuthType Basic AuthName "blog.creke.net SVN" AuthUserFile D:\svn\.htpasswd AuthzSVNAccessFile D:\svn\.ht_svn_authz Require valid-user </Location> #SVN END 具体的配置参数可以查看这里和这里。 其中的.htpasswd是用户密码文件,与apache的一样。 .ht_svn_authz是访问控制文件,可以在svnadmin create后,在conf目录下authz.conf找到该文件带有注释的原型。 如果在blog.creke.net的虚拟主机中加上以上配置,再执行“svnadmin create d:\svn\rep1”后,我们访问http://blog.creke.net/svn/rep1时,就会访问到对应的rep1的仓库。 使用这个方法,apache就会兼做svn服务器,就不需要单独启动svnserve了。 from:http://blog.creke.net/788.html
View Details为了帮助人们升级,我们维护一份描述对现有Apache HTTP Server用户至关重要的信息的文档。这些只是简要说明,您应该能够在新功能文档或src/CHANGES文件中找到更多信息。应用程序和模块开发人员可以在API更新概述中找到API更改的摘要。 本文档描述了服务器行为的变化,这些变化可能要求您更改配置或使用服务器以继续使用2.4,就像您当前使用2.2一样。要利用2.4中的新功能,请参阅新功能文档。 本文档仅描述了从2.2到2.4的变化。如果您从2.0版升级,则还应该查阅升级文档2.0至2.2。 编译时配置更改 运行时配置更改 其他变化 第三方模块 升级时常见的问题 也可以看看 Apache HTTP Server 2.4中的新功能概述 注释 编译时配置更改 编译过程非常类似于2.2版中使用的过程。大多数情况下,您的旧configure命令行(可以在build/config.nice安装的服务器目录中找到)可以使用。默认设置有一些变化。一些细节的变化: 这些模块已被删除:mod_authn_default,mod_authz_default,mod_mem_cache。如果您在2.2中使用mod_mem_cache,请参阅mod_cache_disk2.4。 所有的负载平衡实现已经被移动到独立的,独立的mod_proxy子模块,例如 mod_lbmethod_bybusyness。您可能需要构建并加载配置使用的任何这些内容。 BeOS,TPF以及A / UX,Next和Tandem等较早的平台都已取消平台支持。无论如何,这些被认为是破碎的。 配置:动态模块(DSO)是默认生成的 配置:默认情况下,只加载一组基本的模块。其他LoadModule指令在配置文件中被注释掉。 配置:默认情况下,“最”模块集建成 配置:“真正的”模块集将开发者模块添加到“全部”集 运行时配置更改 授权配置和其他次要配置更改发生了重大变化,可能需要在使用2.4配置文件之前对其进行更改。 授权 任何使用授权的配置文件都可能需要更改。 您应该查看身份验证,授权和访问控制Howto,尤其是Beyond仅授权部分,该部分 解释了控制授权指令应用顺序的新机制。 控制授权模块在与认证用户不匹配时如何响应的指令已被删除:这包括AuthzLDAPAuthoritative,AuthzDBDAuthoritative,AuthzDBMAuthoritative,AuthzGroupFileAuthoritative,AuthzUserAuthoritative和AuthzOwnerAuthoritative。这些指令已经被换成了更具表现力RequireAny, RequireNone和 RequireAll。 如果您使用mod_authz_dbm,则必须移植您的配置以Require dbm-group …代替使用Require group …。 访问控制 在2.2的基础上,客户端的主机名,IP地址,客户端请求的其他特性的访问控制使用的指示做Order,Allow,Deny,和Satisfy。 在2.4中,这种访问控制与使用新模块的其他授权检查相同 mod_authz_host。旧的访问控制成语应该被新的认证机制所取代,尽管为了与旧的配置兼容,mod_access_compat提供了新的模块。 混合旧的和新的指令 混合旧指令一样Order,Allow或Deny以新的希望 Require在技术上是可行的,但不鼓励。mod_access_compat是为支持仅包含旧指令的配置而创建的,以促进2.4升级。请查看下面的示例以更好地了解可能出现的问题。 以下是一些新旧方法可用于执行相同访问控制的示例。 在这个例子中,没有认证,所有请求都被拒绝。 2.2配置:
1 2 |
<span class="kwd">顺序</span><span class="pln">否认</span><span class="pun">,</span><span class="pln">允许 </span><span class="pln">所有人</span><span class="kwd">拒绝</span> |
2.4配置:
1 |
<span class="kwd">要求</span><span class="pln">全部拒绝</span> |
在这个例子中,没有认证,所有的请求都是允许的。 2.2配置:
1 2 |
<span class="kwd">订单</span><span class="pln">允许</span><span class="pun">,</span><span class="pln">拒绝 </span><span class="pln">全部</span><span class="kwd">允许</span> |
2.4配置:
1 |
<span class="kwd">要求</span><span class="pln">所有授予</span> |
在以下示例中,不存在身份验证,并且example.org域中的所有主机都被允许访问; 所有其他主机都被拒绝访问。 2.2配置:
1 2 |
<span class="kwd">为了</span><span class="kwd">拒绝</span><span class="pun">,</span><span class="kwd">允许</span><span class="kwd">拒绝</span><span class="pln">所有 </span><span class="kwd">允许</span><span class="pln">从例子</span><span class="pun">。</span><span class="pln">组织</span> |
2.4配置:
1 |
<span class="kwd">要求</span><span class="pln">主机示例</span><span class="pun">。</span><span class="pln">组织</span> |
在以下示例中,混合旧指令和新指令会导致意外的结果。 混合旧的和新的指令:不按预期工作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<span class="kwd">DocumentRoot </span><span class="str">“/ var / www / html”</span> <span class="pun">< </span><span class="tag">目录</span><span class="str">“/” </span><span class="pun">> </span><span class="kwd">AllowOverride </span><span class="typ">无</span><span class="kwd">顺序</span><span class="pln">拒绝</span><span class="pun">,</span><span class="pln">允许 </span><span class="kwd">拒绝</span><span class="pln">所有 </span><span class="pun"></ </span><span class="tag">Directory </span><span class="pun">></span> <span class="pun">< </span><span class="tag">Location </span><span class="str">> / server-status“ </span><span class="pun">> </span><span class="kwd">SetHandler </span><span class="pln">服务器状态 </span><span class="kwd">需要</span><span class="pln">本地 </span><span class="pun"></ </span><span class="tag">Location </span><span class="pun">></span> <span class="pln"> 访问</span><span class="pun">。</span><span class="pln">日志</span><span class="pun">- </span><span class="pln">GET </span><span class="pun">/ </span><span class="pln">服务器状态</span><span class="lit">403 </span><span class="lit">127.0 </span><span class="pun">。</span><span class="lit">0.1 </span><span class="pln"> 错误</span><span class="pun">。</span><span class="pln">日志</span><span class="pun">- </span><span class="pln">AH01797 </span><span class="pun">:</span><span class="pln">客户端被服务器配置拒绝</span><span class="pun">:</span><span class="pun">/ </span><span class="pln">var </span><span class="pun">/ </span><span class="pln">www </span><span class="pun">/ </span><span class="pln">html </span><span class="pun">/ </span><span class="pln">server-status</span> |
为什么即使配置似乎允许httpd拒绝访问服务器状态?因为mod_access_compat指令优先mod_authz_host于此配置 合并方案中的指令。 这个例子反过来按预期工作: 混合旧的和新的指令:按预期工作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<span class="kwd">DocumentRoot </span><span class="str">“/ var / www / html”</span> <span class="pun">< </span><span class="tag">目录</span><span class="str">“/” </span><span class="pun">> </span><span class="kwd">AllowOverride </span><span class="typ">无</span><span class="kwd">要求</span><span class="pln">全部被拒绝 </span><span class="pun"></ </span><span class="tag">Directory </span><span class="pun">></span> <span class="pun">< </span><span class="tag">Location </span><span class="str">> / server-status“ </span><span class="pun">> </span><span class="kwd">SetHandler </span><span class="pln">server-status </span><span class="kwd">命令</span><span class="pln">拒绝</span><span class="pun">,</span><span class="pln">允许 </span><span class="kwd">拒绝</span><span class="pln">所有 </span><span class="kwd">Allow </span><span class="typ">From </span><span class="lit">127.0 </span><span class="pun">。</span><span class="lit">0.1 </span><span class="pun"></ </span><span class="tag">Location </span><span class="pun">></span> <span class="pln"> 访问</span><span class="pun">。</span><span class="pln">日志</span><span class="pun">- </span><span class="pln">GET </span><span class="pun">/ </span><span class="pln">服务器状态</span><span class="lit">200 </span><span class="lit">127.0 </span><span class="pun">。</span><span class="lit">0.1</span> |
因此,即使混音配置仍然可行,请在升级时尽量避免使用它:或者保留旧的指令,然后在后续阶段迁移到新的指令,或者只是批量迁移所有的指令。 在许多具有身份验证的配置中,其值为ALLSatisfy的缺省值,因此 省略了仅禁用基于主机的访问控制的片段: 2.2配置:
1 2 3 4 5 |
<span class="com">#2.2 config禁用基于主机的访问控制并仅使用认证</span><span class="kwd">Order </span><span class="kwd">Deny </span><span class="pun">,</span><span class="kwd">Allow </span><span class="kwd">Allow </span><span class="pln">from all </span><span class="kwd">AuthType </span><span class="typ">Basic </span><span class="kwd">AuthBasicProvider </span><span class="pln">文件 </span><span class="kwd">AuthUserFile </span><span class="pun">/ </span><span class="pln">example </span><span class="pun">。</span><span class="pln">com </span><span class="pun">/ </span><span class="pln">conf </span><span class="pun">/ </span><span class="pln">users </span><span class="pun">。</span><span class="pln">passwd </span><span class="kwd">AuthName </span><span class="pln">secure </span><span class="kwd">需要</span><span class="pln">有效用户</span> |
2.4配置:
1 2 3 4 |
<span class="com">#不需要替代所需的禁用基于主机的访问控制</span><span class="kwd">AuthType </span><span class="typ">基本</span><span class="kwd">AuthBasicProvider </span><span class="pln">文件 </span><span class="kwd">AuthUserFile </span><span class="pun">/ </span><span class="pln">示例</span><span class="pun">。</span><span class="pln">com </span><span class="pun">/ </span><span class="pln">conf </span><span class="pun">/ </span><span class="pln">users </span><span class="pun">。</span><span class="pln">passwd </span><span class="kwd">AuthName </span><span class="pln">secure </span><span class="kwd">需要</span><span class="pln">有效用户</span> |
在身份验证和访问控制有意义结合的配置中,应该迁移访问控制指令。这个例子允许满足两个标准的请求: 2.2配置:
1 2 3 4 5 6 7 |
<span class="kwd">为了</span><span class="pln">允许</span><span class="pun">,</span><span class="pln">拒绝 </span><span class="kwd">拒绝</span><span class="pln">所有 </span><span class="com">#满足所有是默认的</span><span class="kwd">手托</span><span class="pln">ALL </span><span class="kwd">允许</span><span class="pln">从</span><span class="lit">127.0 </span><span class="pun">。</span><span class="lit">0.1 </span><span class="kwd">AuthType </span><span class="typ">基本</span><span class="kwd">AuthBasicProvider </span><span class="pln">文件 </span><span class="kwd">AuthUserFile </span><span class="pun">/ </span><span class="pln">示例</span><span class="pun">。</span><span class="pln">com </span><span class="pun">/ </span><span class="pln">conf </span><span class="pun">/ </span><span class="pln">users </span><span class="pun">。</span><span class="pln">passwd </span><span class="kwd">AuthName </span><span class="pln">secure </span><span class="kwd">需要</span><span class="pln">有效用户</span> |
2.4配置:
1 2 3 4 5 |
<span class="kwd">AuthType </span><span class="typ">基本</span><span class="kwd">AuthBasicProvider </span><span class="pln">文件 </span><span class="kwd">AuthUserFile </span><span class="pun">/ </span><span class="pln">示例</span><span class="pun">。</span><span class="pln">com </span><span class="pun">/ </span><span class="pln">conf </span><span class="pun">/ </span><span class="pln">users </span><span class="pun">。</span><span class="pln">passwd </span><span class="kwd">AuthName </span><span class="pln">secure </span><span class="pun">< </span><span class="tag">RequireAll </span><span class="pun">> </span><span class="kwd">要求</span><span class="pln">valid-user </span><span class="kwd">要求</span><span class="pln">ip </span><span class="lit">127.0 </span><span class="pun">。</span><span class="lit">0.1 </span><span class="pun"></ </span><span class="tag">RequireAll </span><span class="pun">></span> |
在身份验证和访问控制有意义结合的配置中,应该迁移访问控制指令。此示例允许符合以下任一条件的请求 2.2配置:
1 2 3 4 5 6 7 |
<span class="kwd">订单</span><span class="pln">允许</span><span class="pun">,</span><span class="pln">拒绝 </span><span class="kwd">拒绝</span><span class="pln">从所有 </span><span class="kwd">满足</span><span class="pln">任何 </span><span class="kwd">允许</span><span class="pln">从</span><span class="lit">127.0 </span><span class="pun">。</span><span class="lit">0.1 </span><span class="kwd">AuthType </span><span class="typ">基本</span><span class="kwd">AuthBasicProvider </span><span class="pln">文件 </span><span class="kwd">AuthUserFile </span><span class="pun">/ </span><span class="pln">示例</span><span class="pun">。</span><span class="pln">com </span><span class="pun">/ </span><span class="pln">conf </span><span class="pun">/ </span><span class="pln">users </span><span class="pun">。</span><span class="pln">passwd </span><span class="kwd">AuthName </span><span class="pln">secure </span><span class="kwd">需要</span><span class="pln">有效用户</span> |
2.4配置:
1 2 3 4 5 |
<span class="kwd">AuthType </span><span class="typ">基本</span><span class="kwd">AuthBasicProvider </span><span class="pln">文件 </span><span class="kwd">AuthUserFile </span><span class="pun">/ </span><span class="pln">示例</span><span class="pun">。</span><span class="pln">com </span><span class="pun">/ </span><span class="pln">conf </span><span class="pun">/ </span><span class="pln">users </span><span class="pun">。</span><span class="pln">passwd </span><span class="kwd">AuthName </span><span class="pln">secure </span><span class="com">#隐式地<RequireAny> </span><span class="kwd">需要</span><span class="pln">有效用户 </span><span class="kwd">需要</span><span class="pln">IP </span><span class="lit">127.0 </span><span class="pun">。</span><span class="lit">0.1</span> |
其他配置更改 如下所述,对于特定配置可能需要其他一些小调整。 MaxRequestsPerChild已更名为 MaxConnectionsPerChild,更准确地描述了它的功能。旧名称仍然受支持。 MaxClients已被重新命名为 MaxRequestWorkers,它更准确地描述了它的功能。对于异步MPM,例如 event,最大客户端数量不等于工作线程数量。旧名称仍然受支持。 该DefaultType 指令不再具有任何效果,除非发出警告,否则使用其他值 none。您需要使用其他配置设置在2.4中进行替换。 AllowOverride现在默认为None。 […]
View DetailsPHP安装 由于windows下php扩展5.6的多余7.0,故以php5.6为开发环境。如果对扩展要求不高,可以使用php7,安装过程类似。 约定: 环境安装目录:
1 2 3 4 5 6 |
D:/phpsetup/ |——php |——php-5.6.22-Win32-VC11-x86 |——apache |——mysql |——www |
下载 下载地址: http://php.net/ windows版下载地址: http://windows.php.net/download 官网里Windows的版本有很多。选择哪个版本呢? 如果你的PHP应用程序以FastCGI方式运行,请选择Non-Thread Safe (NTS) 版本; 如果你的PHP应用程序和Apache一起,请选择 Thread Safe (TS) 版本。 本文用的apache+php组合,所以选择ts(Thread Safe)版本。根据操作系统选择x64或者x86。 大多数版本的PHP使用VC9, VC11 or VC14 (Visual Studio 2008, 2012 or 2015分别编译)进行编译的,所以你电脑上需要安装VC运行环境。 电脑需要VC运行环境: VC9 x86 :http://www.microsoft.com/en-us/download/details.aspx?id=5582 VC9 x64 :http://www.microsoft.com/en-us/download/details.aspx?id=15336 VC11 x86 or x64:http://www.microsoft.com/en-us/download/details.aspx?id=30679 VC14 x86 or x64 :http://www.microsoft.com/en-us/download/details.aspx?id=48145 配置PHP 本文以php-5.6.22-Win32-VC11-x86.zip为例。 下载后解压到D:\phpsetup\php\php-5.6.22-Win32-VC11-x86目录。 复制一份php.ini-development文件为php.ini。 需要修改以下地方: 更改自定义扩展目录。 找到
1 |
;extension_dir = "ext" |
更改为
1 |
extension_dir = "D:\phpsetup\php\php-5.6.22-Win32-VC11-x86\ext" |
提示:与apache搭配使用需要写绝对位置。否则扩展加载不了。 开启扩展 往下看,再找到:
1 |
;extension=php_curl.dll |
去掉部分注释:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
extension=php_bz2.dll extension=php_curl.dll extension=php_fileinfo.dll extension=php_gd2.dll extension=php_gettext.dll ;extension=php_gmp.dll ;extension=php_intl.dll ;extension=php_imap.dll ;extension=php_interbase.dll ;extension=php_ldap.dll extension=php_mbstring.dll extension=php_exif.dll ; Must be after mbstring as it depends on it extension=php_mysql.dll extension=php_mysqli.dll ;extension=php_oci8_12c.dll ; Use with Oracle Database 12c Instant Client extension=php_openssl.dll ;extension=php_pdo_firebird.dll extension=php_pdo_mysql.dll ;extension=php_pdo_oci.dll extension=php_pdo_odbc.dll extension=php_pdo_pgsql.dll extension=php_pdo_sqlite.dll extension=php_pgsql.dll ;extension=php_shmop.dll ; The MIBS data available in the PHP distribution must be installed. ; See http://www.php.net/manual/en/snmp.installation.php ;extension=php_snmp.dll extension=php_soap.dll extension=php_sockets.dll extension=php_sqlite3.dll ;extension=php_sybase_ct.dll extension=php_tidy.dll extension=php_xmlrpc.dll extension=php_xsl.dll |
设置默认时区
1 |
date.timezone=PRC |
设置ssl(可选)
1 |
openssl.cafile= cacert.pem |
注意是绝对路径。 添加自定义扩展
1 2 3 4 5 |
[memcache] extension=php_memcache.dll [redis] extension=php_redis.dll |
注意,需要下载对应版本的扩展: 如php_redis-2.2.7-5.6-ts-vc11-x86 区分ts,x86。 下载地址 http://pecl.php.net/package/redis/ http://pecl.php.net/package/memcache http://pecl.php.net/package/SeasLog http://pecl.php.net/package/xdebug http://pecl.php.net/package/yar […]
View Details