cookie相关知识点总结

编    写:袁    亮
时    间:2015-01-15
说    明:cookie相关知识点总结

一、说明
1、http协议是无状态的,每一次请求之间互相独立,为了区分不同的客户端、用户,采用cookie进行标识
2、cookie内容保存在本地txt文件中,类似如下(火狐的):
.ci123.com    TRUE    /flashsale/sadmin    FALSE    1451097200    vip_plat    test3
作用域名        httponly 作用路径            https    过期时间     cookie名     cookie值

二、生存周期
1、服务端设置一个cookie,在http响应头里,会有一个头信息叫set-cookie的
在header头输出之前,不能有任何输出,因此setcookie之前也不能有任何输出
2、浏览器收到该头信息,会写入到客户端的cookie文件中
3、下次发起请求时,会将符合条件的cookie,从本地文件夹中将cookie字符串读取,拼接到http请求头里
只会发送未到过期时间的cookie
该时间以客户端机器为准(因此有时候会出现cookie设置不起来,因为用户电脑的时间不对,导致设置的cookie一直都是已经过期了的)
4、服务器接到http头信息里的cookie数据,将其格式化成相应的cookie数组
同名的cookie只有第一个有效,后面无用(顺序由浏览器根据相应策略决定)

结论:当前页面设置了cookie,本页面是取不到该cookie的,明白了上述流程自然清楚

三、php使用
1、设置cookie:
setcookie(name,value,expire,path,domain,secure,httponly);
2、删除cookie:(跟设置的时候保持一直,只将值设为空即可)
setcookie(name,'',expire,path,domain,secure,httponly);
3、获取cookie:
$val = $_GET['name'];

name:cookie的名称
value:cookie的值(没有值的时候,则注销该cookie)
expire:过期时间,unix时间戳(默认是0,会话,浏览器关闭则失效)
path:在域名的哪个目录下起效
默认只在设置的那个网址目录以及其子目录下有效
比如local.ci123.com/bbs/sub/post_add_sub.php中设置的一个cookie,默认只在/bbs/sub/以及其子目录下有效
domain:在哪个域下有效(只有域名的右前缀值有效,不是随便设置的
test.shop.ci123.com只能设置test.shop.ci123.com,shop.ci123.com,.ci123.com这三个值,默认是test.shop.ci123.com
secure:是否只能通过https发送(很少用,一般都是false)
httponly:js是否可以读取该cookie,一般不允许(设为true)

四、同名cookie
1、cookie名称并不能唯一的标识一个cookie,由三个东西唯一确定:cookie名+作用域(domain)+作用路径(path)
2、cookie名相同的情况下,浏览器会根据一定策略,重新排列cookie字符串,并发送给服务器,服务器只认第一个
1、作用路径顺序(在域名判断之前)
shop.ci123.com/flashsale/访问的时候有两个同名cookie,分别在以下作用路径,则/flashsale/有效
/flashsale
/
2、域名顺序
shop.ci123.com访问的时候有两个同名cookie,分别在以下作用域名,则shop.ci123.com有效
shop.ci123.com
ci123.com

五、工具
firefox的新版firebug插件就集成了cookie插件
chrome也有直接查看cookie的(网址左边的图标)

六、session与cookie的关系
session存储在服务端
一般是通过cookie来标识(不改默认配置的话,是叫PHPSESSID)

统计代码的使用

编    写:袁    亮
时    间:2015-07-06
说    明:统计代码的使用

一、作用
1、作为一个第三方插件,帮我们统计项目的访问人数uv、ip、pv,哪些页面访问的多,都是从哪过来访问的等等一系列数据
2、从各个维度,了解我们项目现在的具体情况,并作为改进的参考

二、常用统计代码
1、51yes:很多老项目里使用了,虽然做的很一般
2、cnzz:很多项目使用了,但是因为使用的太多,树大招风,有时候会被劫持放广告
3、量子统计:小清新,有些功能比较好用
4、百度统计:不允许在项目里使用

三、怎么使用
1、找项目负责人要相应的统计代码
ps:自己必须知道这统计代码怎么来的,上各网站,注册账号,申请统计代码,自己实际操作下
2、在项目的公告底部文件,比如footer.php之类的,加上以下代码
<div style="display:none">第一步那边得到的统计代码</div>
2.1 必须使用display隐藏
2.2 统计代码只能放在页面底部,不允许在中间或者头部添加
2.3 不允许添加非项目负责人发起的统计代码添加

四、怎么查看
1、上相应的统计网站,找负责人要账号密码上去查看
2、重点关注UV,IP,PV,以及跟往前数据的对比,单看某一天的数据没什么意义

开发部署流程

袁亮,15:37 2014-2-13,开发部署上线

说明:
1、本流程主要适用于工作一年内的新人,半个小时内就能搞定的,可以不用按完整的流程来,其他的都需要遵守
2、时间不是太急的情况下,老员工也尽量按该流程来,以降低风险
3、另外,每个程序员都是这么一路犯错下来的,你的水平基本上跟你犯过的错误是成正比的(同一个问题一犯再犯那就另说),所以我们需要学会犯错之后学会去避免它,并且善于从别人的错误教训中吸取经验。

一、需求确定
1、开发之前,必须要明确本次开发的目的,以及实现的方法
a、每个人提出需求的时候,一般都会根据自己的理解、现有的水平,给出相应的解决方案,至于这个方案好还是不好,那就很难说了,所以开发之前,涉及到的相关人员必须要清楚,这次做的根本原因是什么?有没有更好的方法?
b、需求的确定决定了这次开发是否能顺利完成的80%,很多时候,一个很小的改动,可能会减少你们50%以上的工作量。

2、需求的分期完成
a、我们有太多的工作是做的差不多了没上线,或者做着做着就没音讯了,大部分的原因都是因为需求不合理,以及任务分期不合适,总想着事情能一步到位,这会导致开发成本过高,系统太复杂,不敢上线(影响太大),复杂度上升导致bug过多,或者达不到预期,从而导致一堆人花了很长时间的努力全部白费。
b、要学会将一件大的事情,分割成多个小的、可快速完成的事情来实施,快速迭代开发。
c、开发的工作日尽量不要超过3天,1个星期的工作量的就已经是很容易半途而废的了。

3、需求确定之后,开发过程中,不要随意更改、添加
a、在需求讨论的时候,可以把以后可能会扩展的尽量想到,最终的目标等都可以讨论,这个时候需要尽量的详细
b、但在一期开发的时候,只做最核心、最急的几件事情,要做的东西太多,最终只会导致什么都做不了
c、达成共识之后,请需求发起方将讨论确定下来的内容通过邮件的形式发送给相关人员,邮件标题需要有统一前缀,例如【违禁词汇后台改版】- 第一期需求

二、开发过程
1、线上项目修改,必须要有svn,并确认正式版上的相应文件是否已经提交到svn中,并在测试版进行同步
2、开发新功能,必须先在测试机上开发,严禁在正式服务器直接修改
3、需要有相应的测试版数据库,可以找运维组的同学帮忙
4、开发过程中,有不清楚的,需要及时跟需求方进行沟通、反馈
5、必须有修改记录,修改记录里需含有:
a、数据库结构变化,注释
b、新增了哪些文件,做什么
c、修改了哪些文件,分别是为什么
d、各个功能对应哪些文件
6、开发完成之后,需要发送测试确认邮件给需求方,测试之后需要通过邮件回复正式确认,例如【违禁词汇后台改版】- 测试确认

三、部署上线
1、发送邮件,请求运维组同学帮忙备份程序、数据库,并帮忙观察下监控情况,例如【违禁词汇后台改版】- 上线前备份监控
2、将上线步骤通过邮件形式发送给相关人员,没有异议之后,开始下述上线操作。【违禁词汇后台改版】- 上线部署步骤
3、备份完成之后,部署程序到正式版,所有文件更改必须通过svn来更新,不允许直接copy过去上线
4、数据库结构修改部署,先于程序,更改之后马上看下页面以及相应监控是否正常
a、新增:一般不影响旧程序,可以在程序上线之前改,特殊情况自己考虑
b、修改:改了数据库结构之后,旧程序会报错,怎么办?
c、删除:可以在程序上线运行正常之后再删
5、程序文件部署
a、确认正式版的对应文件没有人直接在服务器上修改,如果有,则将正式版的提交,然后在测试版up,再重新进行测试
b、文件新增的,可以在程序上线前更新到正式版
c、更改旧有文件的,如果是后台的,可以先更新后台的,观察没问题之后,前台的如果耦合度不高,可以一个模块一个模块的上线测试
6、上述几步没问题之后,让相关人员在正式版把各个功能都测试一下,并看看其他地方是否会受影响
7、查看相应的数据统计及监控(页面访问、51yes统计、cnzz统计、运维监控、用户反馈)

四、部署出错处理
1、出现问题之后,立即通知相关人员,特别是需要告知自己的leader,协助修复,如果预估修复的时间超过10分钟,项目较重要,则请运维组的同事帮忙进行恢复
2、恢复到旧版本之后,在测试版排查是什么原因导致
3、重新发送新的上线部署步骤邮件,再重新部署
4、没问题之后,邮件告知大家,什么原因导致部署失败,以及如何避免

五、上线后的观察、维护
1、将整个开发过程的开发记录添加到tech后台
2、上线后的一周内,都要时不时的抽时间去了解下相应情况(使用情况、效果如何、用户反馈、有什么不足等)
3、将收集到的情况做相应记录,并记录到后台,为后续开发做准备

项目迁移or测试机搭建流程

迁移测试:
1、项目文件拷贝
2、apache配置,php坏境等(redis,memcache扩展)
3、数据库权限
4、程序调试(记录修改日志)
5、apache日志查看比对,查找访问链接,测试
6、查看错误日志,然后修改
7、与对应编辑一同测试,反馈修改
8、crontab测试,编写
9、完成后,在讨论组里说明

迁移过程:
1、邮件通知相关人员,什么时间点切换,并请求协助观察是否有问题
2、修改相应的配置指向(查看是否需要同步文件)
3、查看新服务器前端页面各个功能是否正常
4、查看新服务器上的apache日志,是否正常
5、查看新服务器上的报错日志
6、查看旧服务器的apache日志,看是否还有访问,如果有,看下是从哪边来的,是否直接加了host,修改之
7、观察2-3天,没有问题之后,本次迁移结束,发送确认邮件给相关人员

简单的签名技术

编    写:袁    亮
时    间:2015-01-27
说    明:基本的数字签名技术

一、为什么需要
1、网络传输的过程中,数据对别人来说是可见的,我们需要保证数据没有被篡改,以保证基本的安全
2、常见使用:
cookie信息
接口调用参数验证

二、如何实现
1、先验条件
1.1 数据生成、数据接收方都需要可控
1.2 两边统一一个相应的密钥,并保存
2、实现
2.1 生成方,在原始数据的后面,根据密钥以及原始数据(其中一部分也行,两边约定好即可),使用散列(MD5或者SHA-1)生成一个签名
2.2 接受放根据接受到的数据,将原始数据使用同样的办法,进行散列,查看与接受到的签名是否一致,如果不同,则非法
3、优点
3.1 实现简单,安全性较高
4、缺点
4.1 如果密钥泄露,更改较为麻烦,得两边同时修改

三、cookie签名demo
1、设置cookie
define("MD_STR","FDSAF$#@dsa!#@4134Eda");

$cstr = '1535917,yuanliang847,暗夜御林';//设置到cookie里的内容
$signstr = md5($cstr.MD_STR);
$cstr .= "|-|".$signstr;

setcookie("uinfo",$cstr,0,"/",'',false,true)

2、cookie解析
define("MD_STR","FDSAF$#@dsa!#@4134Eda");

$uinfo = checkLogin();

function checkLogin(){
if(!isset($_COOKIE['uinfo']) || !$_COOKIE['uinfo']){
return array();
}

$cstr = $_COOKIE['uinfo'];
$tmp = explode("|-|",$cstr);
if(md5($tmp[0].MD_STR) != $tmp[1]){//cookie非法
return array();
}

$data = explode(",",$tmp);
return array('user_id'=>$data[0],'username'=>$data[1],'nickname'=>$data[2]);
}

四、接口参数签名demo
1、client(必须是服务端的,不能是用户可见的过程,比如js)
define("MD_STR","FDSAF$#@dsa!#@4134Eda");

$uid = 1535917;
$username = 'yuanliang847';
$str = "uid={$uid}&username={$username}";//需要传输的原始数据
$http_str = $str."&signstr=".md5($str.MD_STR);//将签名与原始数据一起拼接传输

//...网络数据传输

2、server
define("MD_STR","FDSAF$#@dsa!#@4134Eda");

$uid = isset($_GET['uid'])?intval($_GET['uid']):0;
$username = isset($_GET['username'])?$_GET['username']:'';
$signstr = isset($_GET['signstr'])?$_GET['signstr']:'';

$str = "uid={$uid}&username={$username}";
if(md5($str.MD_STR) != $signstr){
die('参数错误');
}

//...正常业务逻辑处理

3、改进
以上需要对每一个客户端和服务端进行相应的编写,很麻烦
可以编写一个统一的签名函数,来进行相应的验证

五、接口层统一的函数
1、client
define("MD_STR","FDSAF$#@dsa!#@4134Eda");

$p = array(//需要传递的参数,可以是get或者post用
'user_id'    => 1535917,
'username'    => 'yuanliang847',
'nickname'    => '暗夜御林',
);
$p = addSign($p);
$url = "http://api.***.com/***.php?".http_build_query($p);

//...发送接口请求

/**
* 将需要传递的参数数组增加一个签名串
* @data 需要传递的参数数组
* #返回新的参数数组,并增加键值signstr作为签名
*/
function addSign($data){
$str = json_encode($data);
$data['signstr'] = md5($str.MD_STR);
return $data;
}

2、server
define("MD_STR","FDSAF$#@dsa!#@4134Eda");

$is_sign = checkSign($_POST);//看接口是post还是get,传入不同的数据
if(!$is_sign){
die('参数错误');
}

//... 正常业务逻辑处理

/**
* 验证签名串是否正确
* @data 需要验证的参数,包括原始数据以及签名串
* #返回true则正常,否则参数有问题
*/
function checkSign($data){
if(!isset($data['signstr']) || !$data['signstr']){//没有签名
return false;
}

$signstr = $data['signstr'];
unset($data['signstr']);
if(md5(json_encode($data).MD_STR) != $signstr){
return false;
}

return true;
}

育儿网邮寄地址插件

编    写:袁    亮
时    间:2015-01-20
说    明:育儿网邮寄地址插件使用说明

一、问题
1、收货的邮寄地址需要用户填写省市区
2、省市区等信息会变,需要统一管理
3、需要实现联动效果,不需要各个项目都做这一套

二、使用范例
1、代码(参考demo.html文件)
<form name="recvaddress_form">
<select name="province" onchange="ciarea.selcity(this.value,0);" style="width:80px;"></select> 省
<select name="city" style="width:120px;" onchange="ciarea.selarea(this.value,0);"></select> 市
<select name="area" style="width:120px;"></select> 区
</form>
<script type="text/javascript" src="http://shiyong.ci123.com/district/common.js"></script>
<script type="text/javascript">
window.onload = function(){
//ci_province=11;ci_city=1100;ci_area=41306; //编辑的时候,需要默中省市区的时候设置
ciarea.selprovince(ci_province,ci_city,ci_area);
}
</script>
2、需要注意的地方
2.1 form的name必须设置为recvaddress_form,js中有用到
2.2 三个select的name的名称是确定的这三个
2.3 两个onchange事件不能少
2.4 引用common.js
2.5 页面加载的时候,触发数据加载
2.6 编辑地址的时候,需要有默认选中的时候,则设置相应的三个js变量即可

三、参考页面
1、http://shiyong.ci123.com/user/address.php
2、http://user.ci123.com/account/EditUserInfo/detail

http协议的简单总结

编    写:袁    亮
时    间:2014-6-26
说    明:http协议的简单总结

一、基本流程
1、在浏览器输入网址
2、浏览器根据网址,封装http请求头数据包
3、数据包根据地址查找到相应服务器
4、服务器根据头信息进行相应处理并返回返回头信息以及body内容
5、浏览器接收到返回数据,展示body部分内容,并根据头消息进行相应设置,比如cookie等
6、浏览器根据内容进行相应的排版现实,并且运行其中的js交互脚本
7、一次完整的交互完成

二、查找服务器过程
1、根据域名查找本地hosts文件,看是否有对应ip
2、发送到代理,代理去请求数据
3、如果没有,则发送请求到公网dns查询该域名对应的服务器地址
4、cdn加速访问
5、前端代理转发
6、http服务器接收请求,并交给php解析运行
7、服务器将返回的数据再传输回用户的浏览器

三、http常用状态码
200:正常返回
301:永久跳转
302:临时重定向
304:资源未修改,直接使用本地缓存
403:权限不够
404:找不到文件
500:服务器错误,一般是程序语法错误等
502:代理服务器未能接受到正确响应
504:响应超时

crontab书写的一些注意事项

编	写:袁	亮
时	间:2014-03-13
说	明:crontab书写的一些注意事项

一、使用说明:
crontab 是指定时linux服务器,自动的定时去执行一个脚本
一般用于定时去进行一些数据统计,缓存更新,消息提醒等等

二、使用流程:
1、脚本编写,并执行测试(/opt/ci123/php/bin/php *.php),看功能是否正常
	a、定时脚本最好不要在浏览器中执行,因为定时脚本一般执行时间较长,如果在浏览器下执行,有死循环或者太耗时间的语句,中途停止不了,很容易因为这个把数据库等弄挂,项目不能正常访问。而在linux下直接执行,如果卡或异常,可以直接ctrl+c中止。
	b、引入外部文件最好以全路径包含:通过define("FROOT",(dirname(__FILE__)))获取当前文件路径,再通过FROOT来拼接(易于迁移,防止多重include导致相对路径计算错误等)
	c、不允许浏览器访问,防止爬虫等异常访问,加在脚本的前面
		[code]
		if(isset($_SERVER['HTTP_HOST'])){//定时脚本不允许浏览器访问
 		       die();
		}
		[/code]
	d、必须有输出,包括:脚本开始时间、结束时间,各模块的结束时间,方便后期排查

2、加入crontab
	a、crontab -e 进行crontab文件编辑,-e参数不可少,否则会导致将crontab内容清楚,切记
	b、添加一条记录,例如:
		第一行	以#开头的是注释,谁写的,什么时间,做什么用的
		第二行,前5个,分别代表分、时、日、月、周(具体数字代表固定时间;1-5,代表区间;1,4,7代表指定几个时间;*/5代表每5个单位时间执行一次;*代表任意时间;);
			source /etc/profile.d/ice-3.2.1.sh;这个是有ice扩展的时候才加;
			后面是调试时候的执行代码;
			>>/tmp/bbs_static_hour_log 是指将输出以追加的方式记录到/tmp/bbs_static_hour_log这个文件中,命名需规范
			2>&1; 代表不管是正常输出,还是错误提示都记录到日志,照抄即可

		[code]
		#袁亮-2013-12-03,统计bbs每天24小时发帖、回帖等数据
		37 2 * * * ( source /etc/profile.d/ice-3.2.1.sh; /opt/ci123/php/bin/php 		/opt/ci123/www/html/bbs/sadmin/cront/makeStatic.php >>/tmp/bbs_static_hour_log  2>&1;)
		[/code]
	
	

php数组的相关知识

编    写:袁    亮
时    间:2015-01-20
说    明:php数组的相关知识

一、相关概念
1、把有限个变量用同一个名字标识,然后使用不同的名称标识,标识称为下标。本身是一个集合
2、php数组有三种
索引数组 - 带有数字索引的数组
关联数组 - 带有指定键的数组
多维数组 - 包含一个或多个数组的数组

二、常用功能
1、数组创建
$data = array(//索引数组
'user_id'    => 1535917,
'username'    => 'yuanliang847',
'nickname'    => '暗夜御林',
);

$data = array('yuanliang','暗夜御林');//如果数组很小,不需要跟上面似的,写成多行;索引数组

$data['username'] = 'yuanliang847';

$data[] = '暗夜御林';//索引数组,下标值自动加1

第一种方式key后面使用Tab键缩进保持代码对齐,不要打一堆空格,值的前面是一个空格
最后一个值的“,”可以省略,但建议不要省,方便其他人加一个下标的时候,忘了补从而出错
多维数组只是把其中的值value变成一个数组即可
2、循环遍历
foreach($data as $k=>$v){
echo $v."<hr />";
}
php数组使用最多的方式,没有之一
for循环只能对索引数组循环,而foreach可以对任意数组进行循环遍历
$k 是相应的数组下标,$v是对应的值
3、数组计算
$num = count($data);
多维数组也只记第一维的个数

三、数组打印调试
1、var_dump()
var_dump($data);
die();

这是php调试中最常使用的调试打印方法,任意类型的变量都可以打印
2、echo
echo $data['username'];
程序嵌套部分,都是使用的echo把php变量输出成对应的html
3、var_export()
var_export($data);
与var_dump类似,但是这个打印出来的内容,复制出来,可以直接复制给php变量使用,有些时候非常有用
$d = var_export($data,1);//把转化的数据变成字符串,经常会用来生成php文件

四、其他比较有用的功能
1、排序
sort ksort
排序的不同方式,有一堆sort结尾的函数,需要的时候,具体看函数列表
2、数组去重
array_unique
先将值作为字符串排序,然后对每个值只保留第一个遇到的键名,接着忽略所有后面的键名
一般只对一维数组排,多维数组排没有任何意义
3、多个数组合并
array_merge
如果键名有重复,该键的键值为最后一个键名对应的值(后面的覆盖前面的)。如果数组是数字索引的,则键名会以连续方式重新索引
4、查看给定的值在数组中是否存在
in_array($str,$arr)
一般我们只用在索引数组里
5、随机获取一个或者多个元素
array_rand
6、把数组中的值赋给一些变量
$data = array(1535917,'yuanliang847','暗夜御林');
list($user_id,$username,$nickname) = $data;
省去了多次赋值
7、与字符串的互相转换
字符串转索引数组:
explode(separator,string,limit)
数组转字符串:(不要使用join别名,高版本会报错,ps:没记错的话是5.3之后)
implode(separator,array)