使用token来解决用户信息同步问题


编	写:袁	亮
时	间:2015-11-27
说	明:多应用系统用户信息统一安全升级策略

一、问题
	1、post请求之后,后退按钮导致加载失败,提示需要重新提交数据问题的解决
	2、用户信息被抓包,会导致账号泄漏问题
	
二、原因
	1、根据http协议,post请求非幂等,不能缓存,因此有响应头Pragma:no-cache
	2、后退的时候,浏览器会强制提醒用户,确认是否重新输入数据
	3、因此后退会出现白页

三、可能解决思路
	1、post请求换成get请求,绕过限制
		1.1 私密数据不安全,如果链接发给其他人,会导致账号被盗
		1.2 统计代码中,会把这些链接都给存储下来,太危险
	2、对get的数据进行可逆加密并加过期时间
		还是解决不了上面的两个问题
	3、先post发送私密数据过去,然后get跳转
	
四、完整思路
	1、私密数据,必须要走post,不能get
	2、先通过服务器间请求,将私密数据post过去
		2.1 在客户端对数据进行签名及有效期
		2.2 通过post将数据通过服务器与服务器传输
		2.3 服务端返回该数据存储的token(类似session存储)
			为防止服务器返回较慢,导致token丢失,token以客户端传过去的签名为准
		2.4 该数据,只存储一个小时,超过则失效
	3、get形式带上token去请求数据
		3.1 根据token,取到对应的数据
		3.2 用户之后的token要删除,不允许重复使用
		3.3 取出的数据需要验证是否有效期内,并验证签名是否正确
	4、解决了哪些问题
		4.1 没有通过get传输私密数据
		4.2 浏览器没有发起post请求,因此不存在后退刷新的问题
		4.3 私密数据通过服务器间的post请求,因此对用户抓包,并不能获取到这份私密数据
			抓更原始的包那就没办法,虽然不知道原始数据,但还是能登陆到用户账户上
	5、导致的问题及解决办法
		5.1 比之前多了一次http请求,会变的更慢
			在相应的服务器端加host,降低解析时间(同一机房,走内网)
			服务端只做数据存储到内存,不做额外操作降低运行时间
			客户端设置超时,防止卡住
		5.2 memcache存储的数据,存在一定几率丢失
			可以暂时不考虑,概率太低,而且最坏的影响也就是用户某一次可能登陆不上(只有新用户)
		5.3 token丢失或被抓包
			32位的加盐散列,基本可以不考虑被暴力强刷
			token即使丢失,问题也不大,因为token生成之后,用户基本上马上就使用,之后token就失效了
	

使用范例见附件:build_query

Apidoc的安装及使用

整    理:曹燕

时    间:2015-11-27

说    明:Apidoc的安装及使用(官方文档:http://apidocjs.com/

 

1.安装

2.运行

3.apidoc.json配置文件

4.注释中必需的部分

5.继承

6.apidoc的注释规则

(1)@api——定义接口的请求方式、请求路径、标题

(2)@apiDefine——定义一个可重用的块

(3)@apiDescription——api方法的详细介绍

(4)@apiError——出错情况的描述

(5)@apiErrorExample——一个返回出错信息的示例

(6)@apiExample——使用一个接口的示例

(7)@apiGroup——对块进行分类,便于导航条分类

(8)@apiHeader

(9)@apiHeaderExample

(10)@apiIgnore——不被转换的块

(11)@apiName——接口的名称

(12)@apiParam——描述接口的参数

(13)@apiParamExample——接口参数的一个示例

(14)@apiPermission

(16)@apiSuccess——成功时的返回值

(17)@apiSuccessExample——一个成功的返回信息的示例

(18)@apiUse——调用一个已经定义好的块

(19)@apiVersion——一个块的版本信息

 

1.安装

npm install apidoc -g

2.运行

apidoc -i myapp/ -o apidoc/ -t mytemplate/

-i 输入文件的目录,即项目文件夹

-o 输出目录,即放置生成文档的位置

-t 使用的模板,会有默认的模板,当然也可以用自己定义的模板

示例: apidoc -i abc/ -o doc/   apidoc的使用1956

3.apidoc.json配置文件

放在你的工程项目的根目录下,是对项目的概要介绍,包括标题、简要介绍、版本等。

{

"name": "育儿网",

"version": "1.0.0",

"description": "育儿API文档",

"title": "API文档",

"template": {

"withCompare": true,

"withGenerator": true

}

}

其中name、version、description都会被显示出来。

4.注释中必需的部分

/**

* @api {get} /user/:id Request User information

* @apiName GetUser

* @apiGroup User

*/

  • 注释块必须用/** */包围
  • @api {get} /user/:id Request User information

注释块必须以@api开头,否则会忽视这个注释块

  • @apiName必须是一个独一无二的名字
  • @apiGroup的作用是给这个方法分组

5.继承apidoc的使用2448

@apiDefine定义了一个可重用的块,然后其他块调用这个块的时候就写:

@apiUse UserNotFoundError

在生成的文档中会自动填充成UserNotFoundError块的具体内容。

Apidoc中的继承只能继承一层,层数多了会影响可读性。

6.apidoc的注释规则

(1)@api——定义接口的请求方式、请求路径、标题

【开头必需,除非是@apiDefine开头】apidoc的使用2644

Method:必须,方法的请求方式,如get、post、put、delete...

Path:必须,请求路径

Title:可选,可选,用于导航和文章的子标题apidoc的使用2725

(2)@apiDefine——定义一个可重用的块apidoc的使用2753

Name:必须,独一无二的名字,之后引用这个块就是用这个名字

Title:可选,标题

Description:可选,详细介绍,另起一行写apidoc的使用2824

(3)@apiDescription——api方法的详细介绍apidoc的使用2858

Text:必须,api方法的文字介绍

(4)@apiError——出错情况的描述apidoc的使用2902

(Group):可选,有了group值之后该错误会被分组;默认归类为Error 4xx。

{Type}:可选,返回类型,如{Boolean},{Number},{String}等。

Field:必须,返回标识符,例如错误码。

Description:可选,对错误码的描述。apidoc的使用3041

(5)@apiErrorExample——一个返回出错信息的示例

会以预格式化代码输出到页面apidoc的使用3091

{type}:可选,返回信息的格式

Title:可选,这个出错信息的标题

Example:必须,具体的返回信息apidoc的使用3149

(6)@apiExample——使用一个接口的示例

会以预格式化代码输出到页面apidoc的使用3192

{type}:可选,代码的语言

Title:必须,这个例子的标题

Example:必须,使用接口的代码apidoc的使用3246

(7)@apiGroup——对块进行分类,便于导航条分类apidoc的使用3278

Name:必须,分类的名称apidoc的使用3294

(8)@apiHeader

暂略

(9)@apiHeaderExample

暂略

(10)@apiIgnore——不被转换的块apidoc的使用3361

将这句放在块的起始位置,这样进行转换的时候这个块就会被跳过,常常用于一个块还没有开发完毕的时候。

Hint:可选,描述为什么不转换这个块apidoc的使用3432

(11)@apiName——接口的名称apidoc的使用3455

Name:必须,接口的名称,必须是独一无二的名称(允许版本不同的同一名称)apidoc的使用3495

(12)@apiParam——描述接口的参数apidoc的使用3521

(group):可选,所有的参数会被分到这个类里,如果不设置,就分到Parameter。

{type}:可选,参数的类型,如{String}等。

{type{size}}:可选,参数取值的详细信息,如

{number{100-999}}——参数必须是个100-999的数字

{string{2..5}}——参数必须是2-5个字符的字符串

{type=allowedValues}:可选,关于变量允许取值的信息,如

{string="small","huge"}——参数必须是包含”small”或”huge”的字符串

Field:必须,变量名,表示该参数对于接口是必须的

[field]:必须,变量名,表示该参数对于接口不是必须的

=defaultValue:可选,参数的默认取值

Description:可选,参数的描述apidoc的使用3884

(13)@apiParamExample——接口参数的一个示例apidoc的使用3919

{type}:可选,请求信息的格式

Title:可选,示例的标题

Example:必须,请求的具体信息apidoc的使用3973

(14)@apiPermission

暂略

(15)@apiSampleRequest——模拟请求时的urlapidoc的使用4031

(16)@apiSuccess——成功时的返回值apidoc的使用4602

(group):可选,所有的参数会被分到这个类里,如果不设置,就分到Success 200。

{type}:可选,参数的类型,如{String}等。

Field:必须,返回标识符。

Description:可选,成功码的描述。apidoc的使用4723

(17)@apiSuccessExample——一个成功的返回信息的示例apidoc的使用4763

{type}:可选,返回信息的格式

Title:可选,示例的标题

Example:必须,返回的具体信息apidoc的使用4817

(18)@apiUse——调用一个已经定义好的块

已经定义的块是指用@apiDefine定义的块apidoc的使用4869

Name:必须,@apiDefine定义的块的名称apidoc的使用4897

(19)@apiVersion——一个块的版本信息

Group和name值都相同的块,可以进行不同版本的对比。可用于在生成的文档中和之前的版本进行比较,增加和修改的会用绿色标出、删除的会用红色标出。apidoc的使用5000

Version:必须,版本号apidoc的使用5017

https的使用注意事项


编	写:袁	亮
时	间:2015-11-20
说	明:https的使用注意事项

一、全部https的优缺点以及选择
	1、优点
		1.1 安全性高
	2、缺点
		2.2 用户访问会变慢,特别是第一次访问(需要下载证书)
		2.2 开发成本较高,https页面的所有资源都必须是https资源
		2.3 统计代码不能使用,大部分统计代码都不提供https版本
		2.4 服务器端的负载也会变高
	3、其他网站参考
		3.1 百度、淘宝等很多二级域名也不是https
		3.2 京东大部分都不是https
	4、结论
		只针对安全级别高的几个页面采用https即可,不需要整个域名都使用https
		
二、开发过程注意事项
	1、静态资源都必须是https
		1.1 js等请求,浏览器直接会阻止http的请求
		1.2 图片请求,http的不阻止,但是会报warning错误
		1.3 为兼容http和https同时访问,可以写//***.ci123.com/****,会自动根据当前的访问协议加上http或者https
	2、ajax请求
		2.1 ajax请求也必须是同协议的,否则将跨域,不能访问
		2.2 jsonp可以解决这个问题,但最好不要这么做
	3、核心cookie可以设置为仅https访问
		3.1 淘宝中的skt,对应的应该是一个sessionId,就是仅https的
		3.2 这个设置要小心,因为该cookie在http中是访问不到的
		3.3 可以防止cookie被劫持,一般用与session
		3.4 用的不多
	4、关键地方,只配置https,不允许http访问
		4.1 防止用户被引导到http请求中,然后输入了敏感信息
		
三、安全问题
	1、证书伪造:浏览器有提示
	2、引导到http请求,然后盗取

四、其他
	1、https请求可以被缓存
	
附录:
1、HTTPS连接的前几毫秒发生了什么
	http://blog.jobbole.com/48369/ 
2、与HTTP有什么区别?HTTPS的七个误解
	http://www.chinaz.com/web/2015/0320/391752.shtml
3、HTTPS那些事(一)HTTPS原理
	http://www.guokr.com/post/114121/
	日志转载:HTTPS那些事(二)SSL证书
	http://www.guokr.com/post/116169/
	HTTPS那些事(三)攻击实例与防御
	http://www.guokr.com/blog/148613/
		


[PHP]PSR-1/2 育网修订版介绍以及推广

整    理:吴万利

时    间:2015-11-23

说    明:代码规范

关于PSR-1/2

国内靠谱翻译psr-1
国内靠谱翻译psr-2

补充规定

如下的这些都是基于上面规定来的,只是将一些规定明确化

psr-1部分

1 概览

  • 不准使用<\?=短标签

4.2 属性

  • 属性明确规定必须按照"下划线分隔式"
  • 常用变量名
  1. $sql: sql语句
  2. $page: 分页页码
  3. $limit: 每页显示多少条
  4. $ip: 用户ip地址
  5. $dated: 当前时间
  6. $ms: mysqls操作类实例
  7. $pager: 存放分页的html代码
  8. $data: 当前页面主要的数据
  9. $user_id: 用户id
  10. $username: 用户名
  11. $nickname: 用户昵称

psr-2部分

8. [补充]字符串单引号、双引号

  • 纯字符串的时候,使用单引号
  • 字符串中有变量时,使用双引号,变量用{}包含起来。
  1. $show = "你好,{$nickname}!";

9. [补充]用die不用exit

关于CodeSniffer

Github-PHP_CodeSniffer

关于如何操作?

检查我改动的代码

  1. phpcs --standard=PSR2 [files you\'ve changed]

结果展示

  1. FILE: /opt/ci123/www/html/vshop2_dev/svn/lab/src/entity/Product.php
  2. ----------------------------------------------------------------------
  3. FOUND 2 ERRORS AFFECTING 2 LINES
  4. ----------------------------------------------------------------------
  5. 74 | ERROR | Method name "Product::get_discount" is not in camel
  6. | | caps format
  7. 84 | ERROR | Method name "Product::get_photo_url" is not in camel
  8. | | caps format
  9. ----------------------------------------------------------------------

如果没有错误就没有提示

自动修复

  1. phpcbf --standard=PSR1 --standard=PSR2 Slider.php

结果展示

  1. Changing into directory /opt/ci123/www/html/vshop2_dev/svn/lab/src/entity
  2. Processing Slider.php [PHP => 379 tokens in 45 lines]... DONE in 23ms (1 fixable violations)
  3. => Fixing file: 0/1 violations remaining [made 2 passes]... DONE in 49ms
  4. Patched 1 file
  5. Time: 124ms; Memory: 6.75Mb

实际操作步骤说明

jquery – 事件绑定的不同写法


编	写:袁	亮
时	间:2015-11-16
说	明:jquery事件绑定

一、作用
	1、将html显示与js动态交互分离,不在html中写一堆的onclick等js
	2、简化代码,统一处理,防止遗漏以及重复写,比如ajax请求等
	3、结构清晰,分层,html,css,js等独立
	
二、如何绑定事件
	1、bind:向匹配元素添加一个或多个事件处理器
		1.1 所有jquery版本均支持,但1.7版本后,推荐使用on
		1.2 只能对已经存在的元素进行事件绑定
		1.3 了解即可,不使用
	2、live:向当前或未来的匹配元素添加一个或多个事件处理器
		2.1 jquery 1.9版本以上,已经删除
		2.2 使用on来代替
	3、delegate:为指定的元素(被选元素的子元素)添加一个或多个事件处理程序,并规定当这些事件发生时运行的函数。使用 delegate() 方法的事件处理程序适用于当前或未来的元素(比如由脚本创建的新元素)
		3.1 jquery 1.4以上版本支持
		3.2 1.7以下版本的时候可以考虑使用,旧项目,新项目使用不要使用
	4、on【重点】:为指定的元素,添加一个或多个事件处理程序,并规定当这些事件发生时运行的函数。使用 on() 方法的事件处理程序适用于当前或未来的元素(比如由脚本创建的新元素)
		4.1 jquery 1.7以上版本支持
		4.2 尽量使用这个,不要使用其他三种绑定
		
三、简单例子
	$("选择器").on({
		click:function(){
			console.log("我是"+$(this));
			console.log("点击触发");
		},
		mouseout:function(){
			console.log("我是"+$(this));
			console.log("鼠标触发");
		}
	},"子选择器(可选)");

四、常见问题(1.72版本jquery下测试)
	1、元素后加载,事件绑定不成功
		1.1 示范代码
			<code>
			<div class="test">你好</div>
			<script type="text/javascript">
			$(function(){
				//a标签事件绑定
				$(".test a").on({
					click:function(){
						console.log("click");
					}
				});

				//后加载生成dom节点
				$(".test").prepend("<a>测试连接</a><hr>");
			});
			</script>
			</code>
		1.2 因为a标签是后加载的元素,在绑定事件的时候,dom数上还没有该元素,因此绑定失败
		
	2、解决办法1
		2.1 事件绑定在已经存在的父元素上,匹配选择器是否符合
		2.2 示例代码
			<code>
			<div class="test">你好</div>
			<script type="text/javascript">
			$(function(){
				//后加载生成dom节点
				$(".test").prepend("<a>测试连接</a><hr>");

				//a标签事件绑定
				$(".test").on({
					click:function(){
						console.log("click");
					}
				},"a");
			});
			</script>
			</code>
		2.3 优点:绑定事件与处理逻辑脱离,代码更简单易懂
		2.4 缺点:需要注意选择器必须是已经存在的节点,子选择器可以是后加载的元素,不清楚的话,可以直接绑定在document上
				iphone下,会出问题,元素需要添加cursor: pointer;样式,手机使用,不采用这个

	3、解决办法2
		3.1 在元素加载后,执行绑定函数
		3.2 实例代码
			<code>
			<div class="test">你好</div>
			<script type="text/javascript">
			$(function(){
				$(".test").prepend("<a>测试连接</a><hr>");

				$(".test a").on({
					click:function(){
						console.log("click");
					}
				});
			});
			</script>
			</code>
		3.3 优点:各种情况都兼容,不会出现绑定失败
		3.4 缺点:代码可能不是那么好看,绑定事件混在了处理逻辑中

五、使用建议
	1、使用1.7以上版本jquery,2.0以下(不兼容ie8及以下版本)
	2、绑定事件均使用on来绑定,不要使用其他的
	3、对于后加载元素,在加载完成之后进行事件绑定,避免兼容性问题

六、原理,额外拓展,dom树结构(了解即可)
	1、可以使用off来取消事件绑定
	2、可以使用.one,只绑定一次,触发之后就取消绑定
	3、页面dom数结构
	4、事件如何冒泡

附参考文档:
	1、浅谈Jquery中的bind(),live(),delegate(),on()绑定事件方式
	2、jQuery三种事件绑定方式.bind(),.live(),.delegate()
	
	

【svn入门】- 1、初次使用

编  写:袁  亮
时  间:2015-11-02
说  明:从未接触过svn的人,5分钟内学会简单使用svn

一、获取svn地址
1、发送邮件到cjy@corp-ci.com,告知项目名,申请获取svn地址
例如:http://****/demo/
2、如果没有svn账号的,也一并邮件中申请
二、windows中开始使用
1、下载TortoiseSVN安装
2、在需要使用svn的文件目录上右击,选择SVN CheckOut

1

2

3、从svn控制中心,更新最新的程序到本地

3

4、新增的文件,添加到版本库中

4

5、将改动提交到svn控制中心(新增或者修改都需要做这步操作)

5

6

三、linux种开始使用
1、进入到项目开发目录 cd demo/
2、从版本库中checkout下来

1

3、从svn控制中心更新最新版本

2

3、将新文件加入到svn中
3
4、将改动过的内容提交到svn版本控制中心

4

四、常用命令使用
1、【svn入门】- 2、常用命令及练习

2、pdf版本下载:【svn入门】- 初次使用

【web安全规范】 – 2、基本安全防御


编	写:袁	亮
时	间:2015-10-09
说	明:web安全规范 - 2、基本安全防御

一、外部输入过滤
	1、所有外部参数,必须经过处理过滤
		get参数、post参数($_REQUEST)、cookie数据,$_SERVER中的referer,ua,ip等数据
	2、所有过滤,以服务端验证为准,js客户端验证仅仅是为了增强用户体验
		不允许仅仅是在js加了判断验证,服务端没有
	3、只允许使用过滤后的数据,不允许在后面再使用过滤前的原始参数
		$p = isset($_GET['p'])?intval($_GET['p']):1; //过滤参数
		后面只允许只用$p,不允许出现任何直接调用$_GET['p']的地方
	4、过滤方法
		4.1 整型参数,一律采用intval转换
		4.2 短字符串,采用正则验证,常用正则百度,或者参考统一类库
			比如手机号、用户名、邮箱、邮编等等
		4.3 长字符串,非富文本
			比如个人介绍等,过滤html标签(strip_tags),再加过滤sql注入函数(stripSql)
			如果没有验证完全,或者不确定,可以使用mysql_escape_string()进行转义
		4.4 富文本编辑器的长字符串内容
			htmlspecialchars
			采用统一函数或者类库验证过滤
		4.5 这块详见附件 web安全规范 - 参数过滤
	5、严禁使用register_global、extract函数,php配置中也不允许开启register_global
		也不允许自己写代码,将外部变量全部变成内部变量,很多旧项目中就有
		也不要开启magic_quotes,在需要的时候使用addslashes转义

二、报错信息
	1、错误信息只能显示我们定义的对用户友好的内容,不允许显示与实际错误相关的内容
	2、线上不允许开启报错,包括php.ini和程序中的display_errors
	3、特别要注意,类似mysql_error等,只允许记log,不允许输出到页面
	4、必须要记录日志,这是之后排查的唯一依据
	5、日志不允许web直接访问到
	6、更多报错相关信息,请参考内部博客
		http://blog.geekman.vip/archives/27

三、数据存储
	1、log文件不允许存储在web能访问的地方
	2、cookie记录
		2.1 必须设置httponly属性,防止js读取
		2.2 cookie中不允许存储敏感数据,比如用户密码或者邮箱,手机号等
		2.3 cookie内容必须添加签名,并存储,验证cookie的时候必须比对签名是否正确
	3、数据库存储用户密码
		3.1 不允许存储明文密码
		3.2 必须添加盐值做散列
	4、cookie、session等用户登录凭证,需要设置过期时间,防止被劫持之后,一直有效
	5、注意加密算法和编码、散列的区别
		不要误拿编码做加密(base64、urlencode等等)
		不要使用自己编写的加密算法,采用成熟的高安全性算法
	6、日志文件中,不允许记录密码、银行账号等敏感数据

四、数据签名
	1、签名做法可以参考内部博客
		http://blog.geekman.vip/archives/46
	2、cookie存储需要签名
	3、写接口必须加签名
	4、敏感的读数据接口也必须添加签名验证,比如用户邮寄地址等

五、防暴力破解
	1、用户登录等危险操作必须考虑暴力破解的情况
	2、连续错误次数达到一定次数,则需要一个封禁时间
	3、同一个ip同时对多个账号多次尝试也需要处理
	4、发现有人暴力破解的时候,需要有报警机制,比如邮件、短信等

六、业务逻辑bug
	1、发布的时候,进行了相应的过滤,但是编辑的时候未处理,也会导致bug
	2、修改密码的时候,不进行验证,直接修改
	3、购买商品的时候,价格直接通过参数传递结算
	4、找回密码的时候,通过安全问题来验证,但是安全问题可以在登陆的时候直接修改
	5、这些业务逻辑的bug,需要在需求、开发阶段就要多想想,特别是一些比较危险的操作

七、越权访问
	1、所有后台、管理员操作的地方必须要经过权限验证
	2、所有验证必须是通过服务端验证,不允许采用js隐藏,不显示按钮等来完成
	3、每次都必须验证,不要指望在入口那边验证过了,操作的时候就可以不验证
	4、权限验证,不要寄希望与链接、入口别人不知道,浏览器插件、搜索引擎,都有可能泄露
	5、特别要注意调用接口的地方,不要遗漏
	6、所有操作,都必须想想,这是不是一个所有人都可以任意访问的资源,如果不是,都需要权限验证

八、服务器安全
	1、mysql资源
		1.1 除非特殊申请,否则主库增删改查权限,从库查权限
		1.2 给定权限的时候,必须限制ip,一般是内网固定某台
	2、web服务
		不允许使用root账号启动,比如apache等(我们的云主机上有见过root启动的)
		不要安装不用的扩展,很多扩展是有高危漏洞的
	3、redis、memcache资源
		需要绑定ip,一般是内网
		也可设置加账号密码访问
	4、严禁rm -rf命令,同学的同事有过rm -rf之后,损失一个亿的教训
	5、程序源码被直接显示出来
		解析不当+程序员操作不当,导致.bak文件等直接源码显示出来
	6、.svn文件夹等,直接可以遍历扫描
	7、web访问目录层级,web不允许直接访问到项目代码根目录
		/项目代码根目录/webroot/

九、文件上传
	1、上传文件的存储目录,不允许给执行权限【最重要】
	2、上传图片采用其他域名访问,与web服务域名分开
	3、文件扩展名白名单过滤
	4、存储文件名必须系统生成,不允许用户自定义
	5、想了解更多,可以参考内部博客
		http://blog.geekman.vip/archives/301

十、不要调用系统命令
	1、不要在web服务中调用shell命令,比如exec,system,eval之类的
	2、实在要用,shell命令的参数不要是通过web参数带过来的,否则很容易导致系统被攻破

十一、测试环境
	1、重要项目,必须有搭建测试环境(可以在本地搭建)
	2、测试环境的数据库、memcache等资源也必须是用的测试的
	3、不要把调试后门给上传到了线上,因为不知道哪天调试后门就会被人非法访问了
		不要觉得你这个链接从来没公布出去别人不知道,有个东西叫浏览器插件,还有个东西叫抓包

十二、跳转链接
	1、登陆等callback页面,必须要对callback后的链接进行验证
		否则给用户发了一个育儿网的链接,结果用户登陆之后跳到一个恶意网站,在恶意网站提示用户账户密码错误,请重新输入,然后就会导致用户账户密码被盗
	2、进行有根据用户的referer来进行跳转的,referer中的链接也需要验证,可以随意伪造

php发送邮件的相关知识

编	写:袁	亮
时	间:2015-07-28
说	明:php发送邮件的相关知识

一、什么时候需要用到?
	1、系统监控,应用监控报警
	2、相应的项目统计
	3、用户注册、重置密码
	4、发送推广内容(现在很少)
	5、给用户的正式通知
	
二、php中发送邮件的方式
	1、使用封装好的PHPMailer类发送【常用】
		网上下载相应的类文件即可phpmailer
	2、使用smtp类发送
		与PHPMailer类似
	3、PEAR::Net_SMTP组件
		需要引用pear类库中的Net/SMTP.php和Mail/mime.php,服务器上没有的话,直接下载也可以
		据说挺好用的,很强大,没用过,可以尝试下
	4、内置函数mail
		php需要安装正在运行的邮件系统,了解即可,平时不用
	5、popen管道形式发送
		需要配置邮件服务器,了解即可,我也没用过

三、PHPMailer简单demo
	IsSMTP();//使用smtp协议
	$mail->SMTPDebug = false;
	$mail->Host = "smtp.163.com"; //使用哪个smtp服务器,在对应的邮件设置里找SMTP服务器
	$mail->SMTPAuth = true; //需要认证,必选,基本没有不认证的了
	$mail->Username = "ci123_demo"; //邮箱账号,不需要@什么的,需要在邮箱里开启smtp服务,否则失败
	$mail->Password = "nymqjctyjlykkfpt"; //开启smtp服务的时候系统自动设置的密码(163是这样)

	$mail->CharSet = "UTF-8";//编码设置
	$mail->From = "ci123_demo@163.com";//发件人完整邮箱地址
	$mail->FromName = "育儿网";//发件人备注名,可以随意填写,方便自己看即可

	//发送给谁,可以发给多个人,多次执行AddAddress,前面是邮箱地址,后面是备注
	$mail->AddAddress('yuanliang@corp-ci.com', "袁亮");
	$mail->AddCC('629036398@qq.com','暗夜御林');//抄送,暗送是BCC

	$mail->Subject = '邮件标题';
	$content = '邮件测试内容'.date('Y-m-d H:i:s');
	//$mail->Body = $content;//纯文本内容,不能发送html
	$mail->MsgHTML($content);//以html的形式发送,一般用这个,方便排版

	if(!$mail->Send()){
		echo $mail->ErrorInfo;
		die();
	}
	echo 'succ';
	die();
		
四、PHPMailer注意事项
	1、php需要支持sockets,大部分情况下都开启了,phpinfo查看Sockets Support
	2、最常见的错误是需要开启smtp服务,到对应的邮箱里开启
		smtp服务器地址
		邮箱账号
		授权密码,非邮箱登陆密码
	3、需要发送html内容的,需要使用MsgHTML
	4、发送失败的情况下,第一反应是看报错信息,而不是瞎猜
		
五、邮件发送的注意事项
	1、限制
		每个邮件服务器,都有限制邮件数量,163的限制比较少
		出现莫名其妙收不到的情况,可以尝试换一个账号发,换一个账号收等来测试是哪方面有问题
	2、内容过滤
		垃圾内容过滤是邮件服务器最核心的功能,如果对用户发的时候,需要注意内容是否会被过滤,可以先拿自己的账号测试
	3、发送附件
		AddAttachment('文件绝对路径','附件名称');
		
六、邮件协议
	1、POP3
		1.1 POP3允许用户从服务器上把邮件存储到本地主机(即自己的计算机)上,同时删除保存在邮件服务器上的邮件
		1.2 POP3协议允许电子邮件客户端下载服务器上的邮件,但是在客户端的操作(如移动邮件、标记已读等),不会反馈到服务器上
			比如通过客户端收取了邮箱中的3封邮件并移动到其他文件夹,邮箱服务器上的这些邮件是没有同时被移动的
	2、IMAP
		2.1 交互式邮件存取协议,它是跟POP3类似邮件访问标准协议之一
		2.2 IMAP提供webmail 与电子邮件客户端之间的双向通信,客户端的操作都会反馈到服务器上,
			对邮件进行的操作,服务器上的邮件也会做相应的动作
		2.3 IMAP像POP3那样提供了方便的邮件下载服务,让用户能进行离线阅读
	3、SMTP
		3.1 简单邮件传输协议;它是一组用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式
		3.2 SMTP认证,就是要求必须在提供了账户名和密码之后才可以登录 SMTP 服务器,现在已经没有不需要认证的了,除非自己搭
		3.3 发送邮件,必须是开的这个服务
		
附录:
	http://www.w3school.com.cn/php/php_ref_mail.asp
	http://blog.csdn.net/heiyeshuwu/article/details/458170
	http://blog.csdn.net/rainday0310/article/details/6281936
	http://help.163.com/09/1223/14/5R7P6CJ600753VB8.html

php序列化对象导致的错误


编	写:袁	亮
时	间:2014-04-11
说	明:序列化对象导致的错误

一、问题描述
	在迁移blogadmin项目的时候遇到了一个报错:(迁移前php版本:5.2.6、迁移后php版本:5.3.7)

	Fatal error: PostsController::index(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "Information" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition

二、解决过程
	1、根据报错信息搜索,查找到文档:http://www.php.net/manual/zh/language.oop5.serialization.php
	2、按文档里的说明,结合程序,出现问题的原因是:
		a、程序中,会把对象存储会话中(session,session会调用php的serialize函数序列化对象)
		b、在新的页面中,程序从session中,取出数据,并自行调用unserialize函数,反序列化对象,并且正常使用对象
		c、以上要正常使用,必须保证对象所对应的类定义要在unserialize之前,否则反序列化出来的对象会有缺失,从而导致错误
		d、一般情况下,调整session_start和引用类定义文件的顺序即可
		
	3、根据上述信息,调试程序,发现调用对象的时候,类已经定义,而且类定义的引用在session_start之前
	4、经查,发现是该服务器的php配置中,自动开启了session_start,导致session_start永远在类定义前,从而导致错误发生
	5、修改php配置,并重启apache即可

	

php扩展安装的大概流程


编	写:袁	亮
时	间:2015-07-27
说	明:php扩展安装的大概流程

一、安装流程
	1、找到php源码包,进入ext目录
		1.1 注意,是源码包,而不是安装之后的那个文件夹,类似于windows,下载了一个软件包(源码包),安装到了另外一个目录
			使用的时候是直接用的安装好的目录下的程序,而要装扩展,需要的是源码包里的东西
		1.2 注意版本问题,最好是跟已经安装的php同一个版本的源码包,否则很可能会失败
		1.3 例如:192.168.0.249 
			cd /opt/software/centos/php-5.3.27/ext/pdo_mysql
	2、/opt/ci123/php/bin/phpize
		2.1 需要在扩展的那个目录下执行
		2.2 根据自己的php安装目录,找到bin/phpize
		2.3 正常的话,会生成configure
	3、 ./configure --with-php-config=/opt/ci123/php/bin/php-config --with-pdo-mysql=/opt/ci123/mysql/
		3.1 with-pdo-mysql非必须,其他是安装任何扩展都需要的
		3.2 必须在ext目录下执行
	4、make && make install
		4.1 没问题的话,会在最后输出一个目录,看下目录里是否有生成对应的.so文件,比如这次的就是pdo_mysql.so
	5、修改php配置文件,将扩展添加进去
		5.1 php.ini文件,可以通过phpinfo得到其路径,如果那个目录下没有,可以拷贝一份php.ini文件
		5.2 在末尾增加
			[pdo_mysql]
			extension=pdo_mysql.so
	6、验证模块是否正确添加
		php -m|grep pdo_mysql
		ps:如果有输出才算正常
	7、重启http服务,重新加载php
		/opt/ci123/apache/bin/apachectl -t
		/opt/ci123/apache/bin/apachectl restart
		ps:必须-t先检查下配置文件是否正常,别到时候其他人把apache配置改错了,但是因为没重启没问题,被你重启出问题来了