[转载]PHP网站常见安全漏洞,及相应防范措施总结 - 站长之家

mikel阅读(1071)

[转载]PHP网站常见安全漏洞,及相应防范措施总结 – 站长之家.

目前,基于PHP的网站开发已经成为目前网站开发的主流,本文笔者重点从PHP网站攻击与安全防范方面进行探究,旨在减少网站漏洞,希望对大家有所帮助!

一、常见PHP网站安全漏洞

对于PHP的漏洞,目前常见的漏洞有五种。分别是Session文件漏洞、SQL注入漏洞、脚本命令执行漏洞、全局变量漏洞和文件漏洞。这里分别对这些漏洞进行简要的介绍。

1、session文件漏洞

Session攻击是黑客最常用到的攻击手段之一。当一个用户访问某一个网站时,为了免客户每进人一个页面都要输人账号和密码,PHP设置了Session和Cookie用于方便用户的使用和访向。

2、SQL注入漏洞

在进行网站开发的时候,程序员由于对用户输人数据缺乏全面判断或者过滤不严导致服务器执行一些恶意信息,比如用户信息查询等。黑客可以根据恶意程序返回的结果获取相应的信息。这就是月行胃的SQL注入漏洞。

3、脚本执行漏洞

脚本执行漏洞常见的原因是由于程序员在开发网站时对用户提交的URL参数过滤较少引起的,用户提交的URL可能包含恶意代码导致跨站脚本攻击。脚本执行漏洞在以前的PHP网站中经常存在,但是随着PHP版本的升级,这些间题已经减少或者不存在了。

4、全局变量漏洞

PHP中的变量在使用的时候不像其他开发语言那样需要事先声明,PHP中的变量可以不经声明就直接使用,使用的时候系统自动创建,而且也不需要对变 量类型进行说明,系统会自动根据上下文环境自动确定变量类型。这种方式可以大大减少程序员编程中出错的概率,使用起来非常的方便。

5、文件漏洞

文件漏洞通常是由于网站开发者在进行网站设计时对外部提供的数据缺乏充分的过滤导致黑客利用其中的漏洞在Web进程上执行相应的命令。假如在 lsm.php中包含这样一段代码:include($b.”/aaa.php”.),这对黑客来说,可以通过变量$b来实现远程攻击,可以是黑客自已的 代码,用来实现对网站的攻击。可以向服务器提交a.php include=http://lZ7.0.0. 1/b.php,然后执行b.php的指令。

二、PHP常见漏洞的防范措施

1、对于Session漏洞的防范

从前面的分析可以知道,Session攻击最常见的就是会话劫持,也就是黑客通过各种攻击手段获取用户的Session ID,然后利用被攻击用户的身份来登录相应网站。为此,这里可以用以下几种方法进行防范:一是定期更换Session ID,更换Session ID可以用PHP自带函数来实现;二是更换Session名称,通常情况下Session的默认名称是PHPSESSID,这个变量一般是在cookie 中保存的,如果更改了它的名称,就可以阻档黑客的部分攻击;三是对透明化的Session ID进行关闭处理,所谓透明化也就是指在http请求没有使用cookies来制定Session id时,Sessioin id使用链接来传递.关闭透明化Session ID可以通过操作PHP.ini文件来实现;四是通过URL传递隐藏参数,这样可以确保即使黑客获取了session数据,但是由于相关参数是隐藏的,它 也很难获得Session ID变量值。

2、对SQL注入漏洞的防范

黑客进行SQL注入手段很多,而且灵活多变,但是SQL注人的共同点就是利用输入过滤漏洞。因此,要想从根本上防止SQL注入,根本解决措施就是加 强对请求命令尤其是查询请求命令的过滤。具体来说,包括以下几点:一是把过滤性语句进行参数化处理,也就是通过参数化语句实现用户信息的输入而不是直接把 用户输入嵌入到语句中。二是在网站开发的时候尽可能少用解释性程序,黑客经常通过这种手段来执行非法命令;三是在网站开发时尽可能避免网站出现bug,否 则黑客可能利用这些信息来攻击网站;仅仅通过防御SQL注入还是不够的,另外还要经常使用专业的漏洞扫描工具对网站进行漏洞扫描。

3、对脚本执行漏洞的防范

黑客利用脚本执行漏洞进行攻击的手段是多种多样的,而且是灵活多变的,对此,必须要采用多种防范方法综合的手段,才能有效防止黑客对脚本执行漏洞进 行攻击。这里常用的方法方法有以下四种。一是对可执行文件的路径进行预先设定。可以通过safe_moade_exec_dir来实现;二是对命令参数进 行处理,一般用escapeshellarg函数实现;三是用系统自带的函数库来代替外部命令;四是在操作的时候进可能减少使用外部命令。

4、对全局变量漏洞防范

对于PHP全局变量的漏洞问题,以前的PHP版本存在这样的问题,但是随着PHP版本升级到5.5以后,可以通过对php.ini的设置来实现,设 置ruquest_order为GPC。另外在php.ini配置文件中,可以通过对magic_quotes_runtime进行布尔值设置是否对外部 引人的数据中的溢出字符加反斜线。为了确保网站程序在服务器的任何设置状态下都能运行。可以在整个程序开始的时候用 get_magic_quotes_runtime检测设置状态决定是否要手工处理,或者在开始(或不需要自动转义的时候)用 set_magic_quotes_runtime(0)关掉。

5、对文件漏洞的防范

对于PHP文件漏桐可以通过对服务器进行设置和配置来达到防范目的。这里具体的操作如下:一是把PHP代码中的错误提示关闭,这样可以避免黑客通过 错误提示获取数据库信息和网页文件物理路径;二是对open_basedir尽心设置,也就是对目录外的文件操作进行禁止处理;这样可以对本地文件或者远 程文件起到保护作用,防止它们被攻击,这里还要注意防范Session文件和上载文件的攻击;三是把safe-made设置为开启状态,从而对将要执行的 命令进行规范,通过禁止文件上传,可以有效的提高PHP网站的安全系数。

声明:本文由郑州批发市场:http://www.shun-e.com/market/ 原创投稿,尊重他人成果,转载请注明出处!

注:相关网站建设技巧阅读请移步到建站教程频道。

[转载]二维码的生成细节和原理 - 大卫酱_David - 博客园

mikel阅读(857)

[转载][转]二维码的生成细节和原理 – 大卫酱_David – 博客园.

二维码又称QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型:比如:字符,数字,日文,中文等等。这两天学习了一下二维码图片生成的相关细节,觉得这个玩意就 是一个密码算法,在此写一这篇文章 ,揭露一下。供好学的人一同学习之。

关于QR Code Specification,可参看这个PDF:http://raidenii.net/files/datasheets/misc/qr_code.pdf

基础知识

首先,我们先说一下二维码一共有40个尺寸。官方叫版本Version。Version 1是21 x 21的矩阵,Version 2是 25 x 25的矩阵,Version 3是29的尺寸,每增加一个version,就会增加4的尺寸,公式是:(V-1)*4 + 21(V是版本号) 最高Version 40,(40-1)*4+21 = 177,所以最高是177 x 177 的正方形。

下面我们看看一个二维码的样例:

定位图案
  • Position Detection Pattern是定位图案,用于标记二维码的矩形大小。这三个定位图案有白边叫Separators for Postion Detection Patterns。之所以三个而不是四个意思就是三个就可以标识一个矩形了。
  • Timing Patterns也是用于定位的。原因是二维码有40种尺寸,尺寸过大了后需要有根标准线,不然扫描的时候可能会扫歪了。
  • Alignment Patterns 只有Version 2以上(包括Version2)的二维码需要这个东东,同样是为了定位用的。
功能性数据
  • Format Information 存在于所有的尺寸中,用于存放一些格式化数据的。
  • Version Information 在 >= Version 7以上,需要预留两块3 x 6的区域存放一些版本信息。
数据码和纠错码
  • 除了上述的那些地方,剩下的地方存放 Data Code 数据码 和 Error Correction Code 纠错码。

数据编码

我们先来说说数据编码。QR码支持如下的编码:

Numeric mode数字编码,从0到9。如果需要编码的数字的个数不是3的倍数,那么,最后剩下的1或2位数会被转成4或7bits,则其它的每3位数字会被编成 10,12,14bits,编成多长还要看二维码的尺寸(下面有一个表Table 3说明了这点)

Alphanumeric mode字符编码。包括 0-9,大写的A到Z(没有小写),以及符号$ % * + – . / : 包括空格。这些字符会映射成一个字符索引表。如下所示:(其中的SP是空格,Char是字符,Value是其索引值) 编码的过程是把字符两两分组,然后转成下表的45进制,然后转成11bits的二进制,如果最后有一个落单的,那就转成6bits的二进制。而编码模式和 字符的个数需要根据不同的Version尺寸编成9, 11或13个二进制(如下表中Table 3)

Byte mode, 字节编码,可以是0-255的ISO-8859-1字符。有些二维码的扫描器可以自动检测是否是UTF-8的编码。

Kanji mode这是日文编码,也是双字节编码。同样,也可以用于中文编码。日文和汉字的编码会减去一个 值。如:在0X8140 to 0X9FFC中的字符会减去8140,在0XE040到0XEBBF中的字符要减去0XC140,然后把结果前两个16进制位拿出来乘以0XC0,然后再 加上后两个16进制位,最后转成13bit的编码。如下图示例:

Extended Channel Interpretation (ECI) mode主要用于特殊的字符集。并不是所有的扫描器都支持这种编码。

Structured Append mode用于混合编码,也就是说,这个二维码中包含了多种编码格式。

FNC1 mode这种编码方式主要是给一些特殊的工业或行业用的。比如GS1条形码之类的。

简单起见,后面三种不会在本文 中讨论。

下面两张表中,

  • Table 2 是各个编码格式的“编号”,这个东西要写在Format Information中。注:中文是1101
  • Table 3 表示了,不同版本(尺寸)的二维码,对于,数字,字符,字节和Kanji模式下,对于单个编码的2进制的位数。(在二维码的规格说明书中,有各种各样的编码规范表,后面还会提到)

下面我们看几个示例,

示例一:数字编码

在Version 1的尺寸下,纠错级别为H的情况下,编码: 01234567

1. 把上述数字分成三组: 012 345 67

2. 把他们转成二进制: 012 转成 0000001100; 345 转成 0101011001; 67 转成 1000011。

3. 把这三个二进制串起来: 0000001100 0101011001 1000011

4. 把数字的个数转成二进制 (version 1-H是10 bits ):8个数字的二进制是 0000001000

5. 把数字编码的标志0001和第4步的编码加到前面: 0001 0000001000 0000001100 0101011001 1000011

示例二:字符编码

在Version 1的尺寸下,纠错级别为H的情况下,编码: AC-42

1. 从字符索引表中找到 AC-42 这五个字条的索引 (10,12,41,4,2)

2. 两两分组: (10,12) (41,4) (2)

3.把每一组转成11bits的二进制:

(10,12) 10*45+12 等于 462 转成 00111001110
(41,4) 41*45+4 等于 1849 转成 11100111001
(2) 等于 2 转成 000010

4. 把这些二进制连接起来:00111001110 11100111001 000010

5. 把字符的个数转成二进制 (Version 1-H为9 bits ):5个字符,5转成 000000101

6. 在头上加上编码标识 0010 和第5步的个数编码: 0010 000000101 00111001110 11100111001 000010

结束符和补齐符

假如我们有个HELLO WORLD的字符串要编码,根据上面的示例二,我们可以得到下面的编码,

编码 字符数 HELLO WORLD的编码
0010 000001011 01100001011 01111000110 10001011100 10110111000 10011010100 001101

我们还要加上结束符:

编码 字符数 HELLO WORLD的编码 结束
0010 000001011 01100001011 01111000110 10001011100 10110111000 10011010100 001101 0000
按8bits重排

如果所有的编码加起来不是8个倍数我们还要在后面加上足够的0,比如上面一共有78个bits,所以,我们还要加上2个0,然后按8个bits分好组:

00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 01000000

补齐码(Padding Bytes)

最后,如果如果还没有达到我们最大的bits数的限制,我们还要加一些补齐码(Padding Bytes),Padding Bytes就是重复下面的两个bytes:11101100 00010001 (这两个二进制转成十进制是236和17,我也不知道为什么,只知道Spec上是这么写的)关于每一个Version的每一种纠错级别的最大Bits限 制,可以参看QR Code Spec的第28页到32页的Table-7一表。

假设我们需要编码的是Version 1的Q纠错级,那么,其最大需要104个bits,而我们上面只有80个bits,所以,还需要补24个bits,也就是需要3个Padding Bytes,我们就添加三个,于是得到下面的编码:

00100000 01011011 00001011 01111000 11010001 01110010 11011100 01001101 01000011 0100000011101100 00010001 11101100

上面的编码就是数据码了,叫Data Codewords,每一个8bits叫一个codeword,我们还要对这些数据码加上纠错信息。

纠错码

上面我们说到了一些纠错级别,Error Correction Code Level,二维码中有四种级别的纠错,这就是为什么二维码有残缺还能扫出来,也就是为什么有人在二维码的中心位置加入图标。

错误修正容量
L水平 7%的字码可被修正
M水平 15%的字码可被修正
Q水平 25%的字码可被修正
H水平 30%的字码可被修正

那么,QR是怎么对数据码加上纠错码的?首先,我们需要对数据码进行分组,也就是分成不同的Block,然后对各个Block进行纠错编码,对于如何分组,我们可以查看QR Code Spec的第33页到44页的Table-13到Table-22的定义表。注意最后两列:

  • Number of Error Code Correction Blocks:需要分多少个块。
  • Error Correction Code Per Blocks:每一个块中的code个数,所谓的code的个数,也就是有多少个8bits的字节。

举个例子:上述的Version 5 + Q纠错级:需要4个Blocks(2个Blocks为一组,共两组),头一组的两个Blocks中各15个bits数据 + 各 9个bits的纠错码(注:表中的codewords就是一个8bits的byte)(再注:最后一例中的(c, k, r )的公式为:c = k + 2 * r,因为后脚注解释了:纠错码的容量小于纠错码的一半)

下图给一个5-Q的示例(因为二进制写起来会让表格太大,所以,我都用了十进制,我们可以看到每一块的纠错码有18个codewords,也就是18个8bits的二进制数)

数据 对每个块的纠错码
1 1 67 85 70 134 87 38 85 194 119 50 6 18 6 103 38 213 199 11 45 115 247 241 223 229 248 154 117 154 111 86 161 111 39
2 246 246 66 7 118 134 242 7 38 86 22 198 199 146 6 87 204 96 60 202 182 124 157 200 134 27 129 209 17 163 163 120 133
2 1 182 230 247 119 50 7 118 134 87 38 82 6 134 151 50 7 148 116 177 212 76 133 75 242 238 76 195 230 189 10 108 240 192 141
2 70 247 118 86 194 6 151 50 16 236 17 236 17 236 17 236 235 159 5 173 24 147 59 33 106 40 255 172 82 2 131 32 178 236

注:二维码的纠错码主要是通过Reed-Solomon error correction(里 德-所罗门纠错算法)来实现的。对于这个算法,对于我来说是相当的复杂,里面有很多的数学计算,比如:多项式除法,把1-255的数映射成2的n次方 (0<=n<=255)的伽罗瓦域Galois Field之类的神一样的东西,以及基于这些基础的纠错数学公式,因为我的数据基础差,对于我来说太过复杂,所以我一时半会儿还有点没搞明白,还在学习 中,所以,我在这里就不展开说这些东西了。还请大家见谅了。(当然,如果有朋友很明白,也繁请教教我)

最终编码

穿插放置

如果你以为我们可以开始画图,你就错了。二维码的混乱技术还没有玩完,它还要把数据码和纠错码的各个codewords交替放在一起。如何交替呢,规则如下:

对于数据码:把每个块的第一个codewords先拿出来按顺度排列好,然后再取第一块的第二个,如此类推。如:上述示例中的Data Codewords如下:

块 1 67 85 70 134 87 38 85 194 119 50 6 18 6 103 38
块 2 246 246 66 7 118 134 242 7 38 86 22 198 199 146 6
块 3 182 230 247 119 50 7 118 134 87 38 82 6 134 151 50 7
块 4 70 247 118 86 194 6 151 50 16 236 17 236 17 236 17 236

我们先取第一列的:67, 246, 182, 70

然后再取第二列的:67, 246, 182, 70, 85,246,230 ,247

如此类推:67, 246, 182, 70, 85,246,230 ,247 ……… ……… ,38,6,50,17,7,236

对于纠错码,也是一样:

块 1 213 199 11 45 115 247 241 223 229 248 154 117 154 111 86 161 111 39
块 2 87 204 96 60 202 182 124 157 200 134 27 129 209 17 163 163 120 133
块 3 148 116 177 212 76 133 75 242 238 76 195 230 189 10 108 240 192 141
块 4 235 159 5 173 24 147 59 33 106 40 255 172 82 2 131 32 178 236

和数据码取的一样,得到:213,87,148,235,199,204,116,159,…… ……39,133,141,236

然后,再把这两组放在一起(纠错码放在数据码之后)得到:

67, 246, 182, 70, 85, 246, 230, 247, 70, 66, 247, 118, 134, 7, 119, 86, 87, 118, 50, 194, 38, 134, 7, 6, 85, 242, 118, 151, 194, 7, 134, 50, 119, 38, 87, 16, 50, 86, 38, 236, 6, 22, 82, 17, 18, 198, 6, 236, 6, 199, 134, 17, 103, 146, 151, 236, 38, 6, 50, 17, 7, 236, 213, 87, 148, 235, 199, 204, 116, 159, 11, 96, 177, 5, 45, 60, 212, 173, 115, 202, 76, 24, 247, 182, 133, 147, 241, 124, 75, 59, 223, 157, 242, 33, 229, 200, 238, 106, 248, 134, 76, 40, 154, 27, 195, 255, 117, 129, 230, 172, 154, 209, 189, 82, 111, 17, 10, 2, 86, 163, 108, 131, 161, 163, 240, 32, 111, 120, 192, 178, 39, 133, 141, 236

这就是我们的数据区。

Remainder Bits

最后再加上ReminderBits,对于某些Version的QR,上面的还不够长度,还要加上Remainder Bits,比如:上述的5Q版的二维码,还要加上7个bits,Remainder Bits加零就好了。关于哪些Version需要多少个Remainder bit,可以参看QR Code Spec的第15页的Table-1的定义表。

画二维码图

Position Detection Pattern

首先,先把Position Detection图案画在三个角上。(无论Version如何,这个图案的尺寸就是这么大)

Alignment Pattern

然后,再把Alignment图案画上(无论Version如何,这个图案的尺寸就是这么大)

关于Alignment的位置,可以查看QR Code Spec的第81页的Table-E.1的定义表(下表是不完全表格)

下图是根据上述表格中的Version8的一个例子(6,24,42)

Timing Pattern

接下来是Timing Pattern的线(这个不用多说了)

Format Information

再接下来是Formation Information,下图中的蓝色部分。

Format Information是一个15个bits的信息,每一个bit的位置如下图所示:(注意图中的Dark Module,那是永远出现的)

这15个bits中包括:

  • 5个数据bits:其中,2个bits用于表示使用什么样的Error Correction Level, 3个bits表示使用什么样的Mask
  • 10个纠错bits。主要通过BCH Code来计算

然后15个bits还要与101010000010010做XOR操作。这样就保证不会因为我们选用了00的纠错级别和000的Mask,从而造成全部为白色,这会增加我们的扫描器的图像识别的困难。

下面是一个示例:

关于Error Correction Level如下表所示:

关于Mask图案如后面的Table 23所示。

Version Information

再接下来是Version Information(版本7以后需要这个编码),下图中的蓝色部分。

Version Information一共是18个bits,其中包括6个bits的版本号以及12个bits的纠错码,下面是一个示例:

而其填充位置如下:

数据和数据纠错码

然后是填接我们的最终编码,最终编码的填充方式如下:从左下角开始沿着红线填我们的各个bits,1是黑色,0是白色。如果遇到了上面的非数据区,则绕开或跳过。

掩码图案

这样下来,我们的图就填好了,但是,也许那些点并不均衡,如果出现大面积的空白或黑块,会告诉我们扫描识别的困难。所以,我们还要做Masking 操作(靠,还嫌不复杂)QR的Spec中说了,QR有8个Mask你可以使用,如下所示:其中,各个mask的公式在各个图下面。所谓mask,说白了, 就是和上面生成的图做XOR操作。Mask只会和数据区进行XOR,不会影响功能区。(注:选择一个合适的Mask也是有算法的

其Mask的标识码如下所示:(其中的i,j分别对应于上图的x,y)

下面是Mask后的一些样子,我们可以看到被某些Mask XOR了的数据变得比较零散了。

Mask过后的二维码就成最终的图了。

好了,大家可以去尝试去写一下QR的编码程序,当然,你可以用网上找个Reed Soloman的纠错算法的库,或是看看别人的源代码是怎么实现这个繁锁的编码

[转载]HTTP 错误 500.0 - Internal Server Error - 夜落朦空 - 博客园

mikel阅读(842)

[转载]HTTP 错误 500.0 – Internal Server Error – 夜落朦空 – 博客园.

工作需要,需要同时在服务器上运行PHP、ASP、.Net,考虑到方便,我用IIS7.5实现,以下是所需软件列表:

    1、Windows 2008 R2 Standard.
    2、IIS7.5

3、PHP5.3.8 Thread Safe.

5、PHP Manager 

这里不再赘述Windows和IIS7.5的安装方法,详细过程请上百度搜索。

按照正常创建网站流程,以下为简要步骤:

1、创建应用程序池,选择.NetFramework版本为无托管代码,托管管道模式为集成,然后右键点选刚新建的应用程序池,选择常规选项下的启用32位应用程序值为True;

2、创建网站,输入网站名称,应用程序池选择上一步创建好的就用程序池,选择物理路径,确定,并输入默认文档列表;

3、 安装PHP Manager,按照文档步骤设置PHP配置,只需几步便可,然后点击Check phpinfo()进行测试;

然后我遇到了这样的问题,页面出现了如下错误:”出现 HTTP 错误 500.0 – Internal Server Error”,以前也遇到过,用的是php5.2.17版本,很快解决了,按照以前方法,检查目录权限,检查配置项,但是这次问题依旧,反复检查,问题仍 然没有得到解决,郁闷中…………..。

思考一下,即然是用IIS7.5作为服务器进行配置,说不定在IIS官网会有更好的解决办法。上官网,反复搜索查看,眼前一亮,终于找到了解决方法,经实践操作,该问题最终得以解决,哈哈。(特别标注:必须使用x86版本,即使你的服务器是x64版本。

原来出现这个错误是因为PHP5.3是Visual C++ 2008 compiler (VC9)编译的,所以需要在服务器上安装Visual C++ 2008 runtime,至此,整个问题解决。

[转载]在CentOS6.4中安装配置LAMP环境的详细步骤 - Leroy-LIZH - 博客园

mikel阅读(953)

[转载]在CentOS6.4中安装配置LAMP环境的详细步骤 – Leroy-LIZH – 博客园.

本文详细介绍了CentOS6.4系统中安装LAMP服务并对其进行配置的过程,即安装Apache+PHP+MySQL,参照了网上大神的设置,其他Linux发行系统可以参考~

在本文中部分命令操作需要root权限,输入‘su –’命令后输入密码即可切换root身份。

一、修改设置对安装做准备

1. 防火墙设置

  设置/etc/sysconfig/iptables文件允许80端口和3306端口。因为80端口是http协议所使用的端口,如果防火墙禁止80端口的话,网站配置好了也无法从外网访问。3306端口是MySQL数据库的默认端口。使用VIM打开iptables文件并添加规则:

 

1 打开iptables文件进行修改
2 vim /etc/sysconfig/iptables
3 
4 加入下列两行
5 2 -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
6 3 -A INPUT -p tcp -m state --state NEW -m tcp --dport 3306 -j ACCEPT

 

 

 

添加好后文件应该如下图,如果以前修改过该文件责可能和笔者的图中略有不同:

 

 

修改完成注意检查下拼写,不要有错误。保存之后重启防火墙生效:

/etc/init.d/iptables restart

2. 关闭SELINUX

  SELinux 是 2.6 版本的 Linux 内核中提供的强制访问控制(MAC)系统。对于目前可用的 Linux安全模块来说,SELinux 是功能最全面而且测试最充分的。SELinux 提供了比默认ugo+rwx更详细的权限控制。打开SELinux后,即使因为0day漏洞被提权,相应程序的权限在SELinux控制下也不会造成太大 影响。但是在实际应用情况中,SELinux并不实用,没人会闲的去用0day漏洞攻击个人电脑,业务服务器基本上都是用负载均衡设备做流量分发,对外仅开放了仅有的几个端口。所以综合安全性和复杂性来说,SELinux的性价比并不高。修改/etc/selinux/config文件关闭SELinux,设置后如图:

vim /etc/selinux/config

注释掉如下两行,在行首添加#注释。
SELINUX=enforcing
SELINUXTYPE=targeted

在后面增加:
SELINUX=disabled

关闭SELinux后需要重启系统,输入‘shutdown -r now’重启系统。

 

二、开始安装软件

1. MySql的安装和配置

安装MySql:

通过yum软件包管理器安装MySql,管理器会自动安装依赖项,遇到询问直接输入y确认,直到显示“Complete!”完成。
yum install mysql mysql-server

启动MySql
/etc/init.d/mysqld start

设置MySql服务为开机启动
chkconfig mysqld on

复制MySql默认配置文件,直接覆盖/etc/my.cnf
cp /usr/share/mysql/my-medium.cnf /etc/my.cnf

MySql设置:

  设置MySql管理员root账户的密码。

 

输入如下命令后需要连续输入两次密码确认,有询问输入Y同意即可,成功后显示Thanks for using MySQL!。
mysql_secure_installation

 

设置成功后需要重启MySql服务:

1 /etc/init.d/mysqld stop
2 /etc/init.d/mysqld start

 

2. Apache服务的安装和配置

安装httpd
yum install httpd

启动Apache服务
/etc/init.d/httpd start

编辑apache设置
vim /etc/httpd/conf/httpd.conf
查找 #ServerName www.example.com:80
修改成 ServerName www.XXXX.com:80
其中的“www.XXXX.com”自己的域名,没有可设置为localhost,如图

设置Apache服务开机启动
chkconfig httpd on

重启Apache服务
/etc/init.d/httpd restart

安装好Apache服务后,打开系统自带的火狐浏览器,打开localhost这个网址即可看到Apache的示例网页。

 

 

 

3.安装PHP

  安装PHP非常简单:

遇到询问直接输y确认
yum install php

安装PHP插件:

插件包括MySql支持等,遇到询问一如既往的y确认~~
yum install php-mysql php-gd libjpeg* php-imap php-ldap php-odbc php-pear php-xml php-xmlrpc php-mbstring php-mcrypt php-bcmath php-mhash libmcrypt

安装完成后不要忘了重启Apache和MySql:

/etc/init.d/mysqld restart
/etc/init.d/httpd restart

到此软件的安装就结束了,接下来进行配置和测试。

三、修改Apache和PHP的配置

1.修改Apache配置

  作为一个架设在公网上的服务器,我们可不能让服务器所使用的软件版本或者错误等信息暴露网页上,这就需要对Apache进行设置:

编辑文件Apache设置文件
vi /etc/httpd/conf/httpd.conf

44行: 修改 ServerTokens OS 为 ServerTokens Prod
防止错误页显示操作系统名字

76行: 修改 KeepAlive Off 为 KeepAlive On
允许程序性联机

83行: 修改 MaxKeepAliveRequests 100 为 MaxKeepAliveRequests 1000
增加同时连接数

331行: 修改 Options Indexes FollowSymLinks 为 Options Includes ExecCGI FollowSymLinks
允许服务器执行CGI及SSI,防止列出目录

338行: 修改 AllowOverride None 为 AllowOverride All
允许.htaccess

402行: 修改 DirectoryIndex index.html index.html.var 为 DirectoryIndex index.php Default.php index.html index.htm Default.html Default.htm
添加php默认文档

536行: 修改 ServerSignature On 为 ServerSignature Off
防止错误页显示Apache版本

554行: 修改 Options Indexes MultiViews FollowSymLinks 为 Options MultiViews FollowSymLinks
不显示树状目录结构

759行: 根据需要设置为 AddDefaultCharset UTF-8 或者 AddDefaultCharset GB2312
笔者大多数时候都在使用UTF-8编码,所以不进行修改

796行: 修改 #AddHandler cgi-script .cgi 为 AddHandler cgi-script .cgi .pl
允许扩展名为.pl的CGI脚本运行

修改完成后保存退出并重启Apache,删除测试网页:

/etc/init.d/httpd restart

删除测试网页
rm -f /etc/httpd/conf.d/welcome.conf /var/www/error/noindex.html

 

2. 修改PHP配置

编辑php设置文件
vim /etc/php.ini

946行: 修改 ;date.timezone = PRC 为 date.timezone = PRC (去掉分号)

386行: 修改 disable_functions = 为 disable_functions = passthru,exec,system,chroot,scandir,chgrp,chown,shell_exec,proc_open,proc_get_status,ini_alter,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,stream_socket_server,escapeshellcmd,dll,popen,disk_free_space,checkdnsrr,checkdnsrr,getservbyname,getservbyport,disk_total_space,posix_ctermid,posix_get_last_error,posix_getcwd,posix_getegid,posix_geteuid,posix_getgid,posix_getgrgid,posix_getgrnam,posix_getgroups,posix_getlogin,posix_getpgid,posix_getpgrp,posix_getpid,posix_getppid,posix_getpwnam,posix_getpwuid,posix_getrlimit,posix_getsid,posix_getuid,posix_isatty,posix_kill,posix_mkfifo,posix_setegid,posix_seteuid,posix_setgid,posix_setpgid,posix_setsid,posix_setuid,posix_strerror,posix_times,posix_ttyname,posix_uname
设置PHP的禁用函数,若程序中需要使用的函数可以删除掉。

432行: 设置 expose_php = Off
禁止显示php版本的信息

745行: 设置 magic_quotes_gpc = On
打开magic_quotes_gpc,用于防止SQL注入

229行: 设置 short_open_tag = ON
支持php短标签

380行: 设置 open_basedir = .:/tmp/
设置允许访问的目录和/tmp/目录,防止php木马跨站

在CentOS6.4中安装配置LAMP环境的详细步骤

  本文详细介绍了CentOS6.4系统中安装LAMP服务并对其进行配置的过程,即安装Apache+PHP+Mysql,参照了网上大神的设置,其他Linux发行系统可以参考~

在本文中部分命令操作需要root权限,输入‘su –’命令后输入密码即可切换root身份。

一、修改设置对安装做准备

1. 防火墙设置

  设置/etc/sysconfig/iptables文件允许80端口和3306端口。因为80端口是http协议所使用的端口,如果防火墙禁止80端口的话,网站配置好了也无法从外网访问。3306端口是MySql数据库的默认端口。使用VIM打开iptables文件并添加规则:

 

1 打开iptables文件进行修改
2 vim /etc/sysconfig/iptables
3 
4 加入下列两行
5 2 -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
6 3 -A INPUT -p tcp -m state --state NEW -m tcp --dport 3306 -j ACCEPT

 

 

 

添加好后文件应该如下图,如果以前修改过该文件责可能和笔者的图中略有不同:

 

 

修改完成注意检查下拼写,不要有错误。保存之后重启防火墙生效:

/etc/init.d/iptables restart

2. 关闭SELINUX

  SELinux 是 2.6 版本的 Linux 内核中提供的强制访问控制(MAC)系统。对于目前可用的 Linux安全模块来说,SELinux 是功能最全面而且测试最充分的。SELinux 提供了比默认ugo+rwx更详细的权限控制。打开SELinux后,即使因为0day漏洞被提权,相应程序的权限在SELinux控制下也不会造成太大 影响。但是在实际应用情况中,SELinux并不实用,没人会闲的去用0day漏洞攻击个人电脑,业务服务器基本上都是用负载均衡设备做流量分发,对外仅开放了仅有的几个端口。所以综合安全性和复杂性来说,SELinux的性价比并不高。修改/etc/selinux/config文件关闭SELinux,设置后如图:

按 Ctrl+C 复制代码

按 Ctrl+C 复制代码

关闭SELinux后需要重启系统,输入‘shutdown -r now’重启系统。

 

二、开始安装软件

1. MySql的安装和配置

安装MySql:

 

按 Ctrl+C 复制代码

按 Ctrl+C 复制代码

 

MySql设置:

  设置MySql管理员root账户的密码。

 

输入如下命令后需要连续输入两次密码确认,有询问输入Y同意即可,成功后显示Thanks for using MySQL!。
mysql_secure_installation

 

设置成功后需要重启MySql服务:

1 /etc/init.d/mysqld stop
2 /etc/init.d/mysqld start

 

2. Apache服务的安装和配置

按 Ctrl+C 复制代码

按 Ctrl+C 复制代码

安装好Apache服务后,打开系统自带的火狐浏览器,打开localhost这个网址即可看到Apache的示例网页。

 

 

 

3.安装PHP

  安装PHP非常简单:

遇到询问直接输y确认
yum install php

安装PHP插件:

插件包括MySql支持等,遇到询问一如既往的y确认~~
yum install php-mysql php-gd libjpeg* php-imap php-ldap php-odbc php-pear php-xml php-xmlrpc php-mbstring php-mcrypt php-bcmath php-mhash libmcrypt

安装完成后不要忘了重启Apache和MySql:

/etc/init.d/mysqld restart
/etc/init.d/httpd restart

到此软件的安装就结束了,接下来进行配置和测试。

三、修改Apache和PHP的配置

1.修改Apache配置

  作为一个架设在公网上的服务器,我们可不能让服务器所使用的软件版本或者错误等信息暴露网页上,这就需要对Apache进行设置:

按 Ctrl+C 复制代码

按 Ctrl+C 复制代码

修改完成后保存退出并重启Apache,删除测试网页:

/etc/init.d/httpd restart

删除测试网页
rm -f /etc/httpd/conf.d/welcome.conf /var/www/error/noindex.html

 

2. 修改PHP配置

 

按 Ctrl+C 复制代码

按 Ctrl+C 复制代码

 

修改完成保存后重启服务:

/etc/init.d/mysqld restart
/etc/init.d/httpd restart

 

四、 测试PHP探针页面

 

 

  输入“vim /var/www/html/index.php添加PHP探针页面并输入以下代码:

 

1 <?php
2     phpinfo();
3 ?>

 

保存退出后在浏览器中输入localhost查看php信息:

 

 

设置文档文件夹权限:

chown apache.apache -R /var/www/html

 

LAMP服务器配置完成。

[转载] 悬赏¥15000.00 寻求公司内部使用拼车APP - iPhone - APP开发 - 猪八戒网

mikel阅读(959)

[转载]寻求公司内部使用拼车APP – iPhone – APP开发 – 猪八戒网.

具体要求:

背景:
我们公司在厦门,目前在泉州、石狮、漳州等有项目,经常会有来往。想实现,如有车的职员和没车职员,信息共享,拼车去,有车的职员可以得到相应有补助。

实在的目的和要求:
1、        用户名登录验证;公司内部使用。
2、        有车职员发布拼车信息,如从厦门至泉州,目前可提供4个车位。
3、        无车职员发布拼车需求,如从泉州至厦门,需求人共2人。
4、        无车职员可查询开车人员的信息,并直接加入。加入后,空余车位少一位。
5、        有车人员发布拼车信息时,最好有线路信息,如从厦门至泉州时,东渡——仙岳路——翔安高速——泉州。
6、        当拼车前往目的地后,判断相关人员是否有到该地点,如有三人从厦门至泉州后,到泉州后,让三人登录软件后,点击确认,取该人员的定位信息。
7、        补助信息:有车人员,拼车完成后,补助150元(管理员可后台调整),可查询自己所有记录和补助金额。
8、        无车人员可查询所有记录。
9、        查看信息时,可直接拨打相关人员手机。
10、        能提供相关报表,如本月厦门到各地有多少记录,补助多少等,销售部去各地多少次等。

支持平台:
IOS、Android

 

[转载]移动版网页以及Web App的那些meta们 - 萧瑟56 - 博客园

mikel阅读(941)

转载移动版网页以及Web App的那些meta们 – 萧瑟56 – 博客园.

移动版网页以及Web App的那些meta们

如今智能机遍布大街小巷,过年回家(农村的),村里人尽然也在讨论抢不上小米的事 情,看来,移动时代已经来临,而且很飞速,所以,如今的前端攻城师们要大 跨步的迈向移动互联网了,更何况Web App也应用广泛,可能原理还一样,但是一定会有新的东西出现,那就从“头”开始,看看头部那些Meta的新玩意。

1、

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />

这是一个移动端最常用的meta,定义页面的缩放,如上代表宽度以终端宽度为准,并且不允许用户缩放,更多属性如下:
width  — 宽度(范围从200到10,000,默认为980像素/device-width缩放至终端宽度)
height  — 高度(范围从223到10,000)
initial-scale  — 初始的缩放比例 (范围从 > 0 到 10)
minimum-scale  — 允许用户缩放到的最小比例
maximum-scale  — 允许用户缩放到的最大比例
user-scalable  —  用户是否可以手动缩放 (no,yes)
target-densitydpi  —  dpi_value | device-dpi | high-dpi | medium-dpi | low-dpi 定义为每英寸点的数量(dpi)

2、

<meta name="format-detection" content="telephone=no" />

禁止把数字转化为拨号链接

3、

<meta content="email=no" name="format-detection" />

禁止把邮箱地址作为邮件发送

4、

<meta name="apple-mobile-web-app-capable" content="yes" />

隐藏浏览器的工具栏和菜单栏,看到apple了吧,对iso系统起用

5、

<meta name="apple-mobile-web-app-status-bar-style" content="black" />

默 认值为 default(白色),可以定为black(黑色)和black-translucent(灰色半透明),需要说明的是值为“black- translucent”将会占据页面位置,浮在页面上方(会覆盖页面 20px高度 iphone4和itouch4的Retina屏幕为40px)

6、

<meta name="apple-touch-fullscreen" content="yes">

“添加到主屏幕“后,全屏显示

介于说到了“头”,也说到了Web App,那就捎带说说两个苹果私有link,
1、

<link rel="apple-touch-icon-precomposed" href="iphone_logo.png" sizes="72x72" />

这个 link 就是设置 Web App 的放置主屏幕上 icon 文件路径,href就是你ico的文件路径,sizes可以根据不同分辨率,对应不同的图片,尺寸如下:

IOS设备 最适尺寸(px)
iPhone 和 iTouch 57 x 57
retina iPhone 和 retina iTouch 114 x 114
iPad 72 x 72
retina iPad 144 x 144

如果没有指明 <sizes> 属性的大小,则默认值为57×57。
如 果所有的 <link> 标签序列中都没有符合官方推荐的最适尺寸的话,那么IOS会从所有比推荐的最适尺寸大的图标中选择尺寸最小的那一个,如果所有的 <link> 标签序列中的图标都比当前推荐的最适尺寸小的话,IOS会从这些图片中自动选择最大的那个来作为启动图标。
如果整个页面都没有指定任何的 apple-touch-icon 的图标的话,IOS则会自动去网站根目录寻找有 apple-touch-icon 和 apple-touch-icon-precomposed 前缀的图标文件。

2、

<link rel="apple-touch-startup-image" href="logo_startup.png" media="(device-width: 320px)" />

这个 link 就是设置启动时候的界面,可用媒体查询调用不同图片

Web App 才刚刚开始—

[原创]PHP中文保存到mySQL乱码问题

mikel阅读(1163)

最近又转PHP了,做了个简单的CRUD例子,发现存储到MySQL中的中文变成了“???”,于是百度了下,发现有如下问题的还很多

大多原因是因为没有设置mySQL的字符设置的问题

  1. PHP+MySQL出现中文乱码的原因。

    1. MYSQL数据库的编码是utf8,与PHP网页的编码格式不一致,就会造成MYSQL中的中文乱码。

    2. 使用MYSQL中创建表、或者选择字段时设置的类型不是utf8,而网页编码不是utf8,也可能造成MYSQL中文乱码.

    3. PHP页面的字符集与数据库的编码不一致。

    4. PHP连接MYSQL数据库,操作是设定的语句指定的编码和页面编码,PHP页面编码不一致。

    5. 用户提交的HTML页面编码,和显示数据的页面编码不一致 ,就肯定会造成PHP页面乱码.

  2. 怎么解决中文乱码的问题。

    1. 网页编码设置。一般在HTML代码中的文件头<html>中加入属性:

    <meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″>

    保证,网页是”utf-8″编码。

    2. PHP代码设置。在php代码的开始部分加入以下代码:

    header(”Content-type: text/html;charset=utf-8″);

    且要求保存的文件编码方式是utf-8(可以用EditPlus打开设置,如下图),这样就保证了该文件也是utf-8编码。

    3. 数据库中表的字段中存储中文的部分,要设置为utf8_general_ci类型。

    4.PHP在连接数据库操作时,要设置操作的字段类型为utf8,设置方法如下:

    mysql_connect(’localhost’,’user’,’password’);mysql_select_db(’db’);mysql_query(”set names utf8;”); //**设置字符集***

  3. 实例对比。通过上面的分析,我们按照解决方案,得到了正确的中文编码存储在MySQL中,效果如下图所示:

 

[转载]MySQL mysql_fetch_array 函数取得查询结果中的一行作为数组_PHP+MySQL数据库教程

mikel阅读(1078)

[转载]MySQL mysql_fetch_array 函数取得查询结果中的一行作为数组_PHP+MySQL数据库教程.

mySQL_fetch_* 列函数

mySQL_fetch_* 列函数的主要功能是从查询返回的结果集中取得相关的查询结果,主要包括:

  • mySQL_fetch_array():从结果集中取得一行作为关联数组或索引数组,或二者兼有
  • mysql_fetch_row():从结果集中取得一行作为枚举数组
  • mysql_fetch_assoc():从结果集中取得一行作为关联数组
  • mysql_fetch_object():从结果集中取得一行作为对象
  • mysql_fetch_field():从结果集中取得字段信息并作为对象返回
  • mysql_fetch_lengths():取得结果集中取得一行每个字段内容输出的长度

mysql_fetch_array()

mysql_fetch_array() 函数用于从结果集中取得一行作为关联数组或索引数组,或二者兼有。成功返回一个数组,否则返回 FALSE 。

语法:

array mysql_fetch_array( resource result [, int result_type] )
参数说明:
参数 说明
result 查询函数(如 mysql_query)返回的数据集资源
result_type 可选常量,标明数组结果类型,可接受值如下:

  1. MYSQL_BOTH:默认,得到一个同时包含关联和数字索引的数组,用字段名作为键名
  2. MYSQL_ASSOC:只得到关联索引的数组
  3. MYSQL_NUM:只得到数字索引的数组

例子 1 ,使用 MYSQL_NUM :

<?php
$conn = @mysql_connect("localhost","root","root123");
if (!$conn){
    die("连接数据库失败:" . mysql_error());
}

mysql_select_db("test", $conn);
mysql_query("set character set 'gbk'");

$result = mysql_query("SELECT uid,username FROM user");
while($row = mysql_fetch_array($result, MYSQL_NUM)){
    echo "用户ID:".$row[0]."<br />";
    echo "用户名:".$row[1]."<br />";
}
?>

浏览器输出:

用户ID:1
用户名:admin
用户ID:2
用户名:小明
用户ID:3
用户名:Jack
用户ID:4
用户名:小王

例子 2 ,使用 MYSQL_ ASSOC :

//重复代码省略
$result = mysql_query("SELECT uid,username FROM user");
while($row = mysql_fetch_array($result, MYSQL_ ASSOC)){
    echo "用户ID:".$row['uid']."<br />";
    echo "用户名:".$row['username']."<br />";
}

浏览器输出内容同上。

当使用 MYSQL_BOTH 或省略该参数是,将同时具有 MYSQL_NUM 与 MYSQL_ ASSOC 的特性。

说明

  1. 本函数返回的字段名作为数组键值是区分大小写的
  2. 用 mysql_fetch_array() 并不明显 比用 mysql_fetch_row() 慢,而且还提供了明显更多的值
  3. 该函数只从当前数据指针取得一行数据作为结果返回,如果执行过一次,会将数据指针指向下一列数据
  4. 如果要取得多行或者全部数据,需要使用循环结构将数据逐行取出
  5. 如果结果中的两个或以上的列具有相同字段名,最后一列将优先。要访问同名的其它列,必须用该列的数字索引或给该列起个别名

[转载]获取mysql结果集的几个函数的区别 - PHP小菜鸟 -- PHP技术博客,苦逼的程序猿

mikel阅读(1087)

[转载]获取mysql结果集的几个函数的区别 – PHP小菜鸟 — PHP技术博客,苦逼的程序猿.

获取mySQL结果集有四个函数分别是  mySQL_fetch_row  mySQL_fetch_array mysql_fetch_object mysql_fetch_assoc

一直以来,有很多初学者搞不懂这些Mysql中从查询结果集中取得数据的几个函数之间有什么区别,今天我就针对这几个
函数做下解释以及测试,先给大家段代码

<!--?php <br ?--> $link=mysql_connect('localhost','root','');
mysql_select_db('blog',$link);
$sql = "select * from Emlog_blog";
$result = mysql_query($sql);
while($row = mysql_fetch_row($result)){
echo $row['gid'].'::'.$row[1].'
';
}
$result = mysql_query($sql);
while($row = mysql_fetch_array($result)){
echo $row['gid'].'::'.$row['title'].'
';
}
$result = mysql_query($sql);
while($row = ($result)){
echo $row-&gt;gid.'::'.$row-&gt;title."
";
}
$result = mysql_query($sql);
while($row = mysql_fetch_assoc($result)){
echo $row['gid'].'::'.$row['title'].'
';
}
?&gt;

分析:
mysql_fetch_row,这个函数是从结果集中取一行作为枚举数据,从和指定的结果标识关联的结果集中取得一行数据
并作为数组返回。每个结果的列储存在一个数组的单元中,偏移量从 0 开始。 注意,这里是从0开始偏移,也就是
说不能用字段名字来取值,只能用索引来取值,所以如下代码是取不到值的:
while($row = mysql_fetch_row($res)){
echo $row[‘gid’].’::’.$row[1].”;
} //这里的$row[‘gid’] 取不到值。
mysql_fetch_array,从结果集中取得一行作为关联数组,或数字数组,或二者兼有,除了将数据以数字索引方式储
存在数组中之外,还可以将数据作为关联索引储存,用字段名作为键名。 也就是说他得到的结果像数组一样,可以
用key或者索引来取值,所以
while($row = mysql_fetch_array($res)){
echo $row[‘gid’].’::’.$row[‘title’].”;
}//这里$row[‘gid’],$row[‘title’]都能得到相应的值。
mysql_fetch_object,顾名思义,从结果集中取得一行作为对象,并将字段名字做为属性。所以只有这样才能取到值
while($row = mysql_fetch_object($res)){
echo $row->gid.’::’.$row->title.””;
}
mysql_fetch_assoc,从结果集中取得一行作为关联数组,也就是说这个函数不能像mysql_fetch_row那样用索引来
取值,只能用字段名字来取,所以
while($row = mysql_fetch_assoc($res)){
echo $row[‘gid’].’::’.$row[1].”;
} //$row[1]这样是取不到值的

总结
mysql_fetch_array函数是这样定义的:array mysql_fetch_array ( resource result [, int result_type]),返回根
据从结果集取得的行生成的数组,如果没有更多行则返回 FALSE。
mysql_fetch_array() 中可选的第二个参数 result_type 是一个常量,可以接受以下值:MYSQL_ASSOC,MYSQL_NUM 和
MYSQL_BOTH。其中:
1、mysql_fetch_assoc($result)==mysql_fetch_array($result,MYSQL_ASSOC);
2、mysql_fetch_row($result)==mysql_fetch_array($result,MYSQL_NUM);
所以mysql_fetch_array()函数在某种程度上可以算是mysql_fetch_row()与 mysql_fetch_assoc()的集合。另外,
mysql_fetch_array()另外还有MYSQL_BOTH参数,将得到一个同时包含关 联和数字索引的数组。
在来说句 $row = $db->fetch_array($query);
$db是人数据库操作类,$db->fetch_array($query),fetch_array($query)是那个db类里的方法,
$row = $db->fetch_array($query)这句的意思是从记录集$query中得到数据库中的一行记录。
不用类可这样实现

@mysql_select_db($database,$conn);
$query=mysql_query($sql);
while($row=mysql_fetch_array($query)){
$rows[]=$row;
}

[转载]微信公众平台开发模式,成为开发者,实现自动回复和用户的关注事件的监听 - My bobo - 博客频道 - CSDN.NET

mikel阅读(1083)

[转载]微信公众平台开发模式,成为开发者,实现自动回复和用户的关注事件的监听 – My bobo – 博客频道 – CSDN.NET.

公司不忙的时候,自己研究了下微信公众平台。然后各种找资料各种研究。

这是我自己的php代码

<?php
/**
  * wechat php test
  */


//define your token
define("TOKEN", "token");
$wechatObj = new wechatCallbackapiTest();
if(isset($_GET["echostr"])){ #验证过token,成为开发者之后,可以直接$wechatObj->responseMsg();
$wechatObj->valid();
}else{
$wechatObj->responseMsg();
}




class wechatCallbackapiTest
{
public function valid()
    {
        $echoStr = $_GET["echostr"];


        //valid signature , option
        if($this->checkSignature()){
        echo $echoStr;
        exit;
        }
    }


    public function responseMsg()
    {
//get post data, May be due to the different environments
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];


      //extract post data
if (!empty($postStr)){
                
              $postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); #这里有从用户通过公众平台接收过来的数据,具体是什么类型的数据,开发者文档上写的很清楚,可以去上面查。
                $fromUsername = $postObj->FromUserName;
                $toUsername = $postObj->ToUserName;
                $keyword = trim($postObj->Content);
$msgType = $postObj->MsgType;
                $time = time();
switch( $msgType ){
case "text": #这个xml格式的数据是你服务器上的数据,是要传回公众平台的。我在这刚开始有点糊涂了
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag>

</xml>";         

#这里是我自己写的,关于时间的自动回复     
if( $keyword =='时间' || $keyword =='time' || $keyword =="shijian"){
$contentStr = date("Y-m-d H:i:s",time());
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}
else
{
$msgType = "text";
$contentStr = "欢迎您来到博论天涯!";
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}

break;


case "event": #这个是事件的操作,当关注的时候自动回复
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag>
</xml>";
$event = $postObj->Event;
$msgType = "text";
if( $event =='subscribe'){
$contentStr = "这里是博论天涯,谢谢您关注!";
}
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
break;
}
                


        }else {
        echo "";
        exit;
        }
    }

private function checkSignature() #这个函数验证过之后就可以删除了
{
        $signature = $_GET["signature"];
        $timestamp = $_GET["timestamp"];
        $nonce = $_GET["nonce"];
       
$token = TOKEN;
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr);
$tmpStr = implode( $tmpArr );
$tmpStr = sha1( $tmpStr );

if( $tmpStr == $signature ){
return true;
}else{
return false;
}
}
}


?>