人会长大三次

在博客上贴过一篇文章,《成熟的标志是什么?》http://www.guoxiongjie.com/91/,现在已经记不得当时为什么要贴这篇文章,可能是当时觉得这篇文章写得好,也可能是当时自己处于想成熟的阶段。

不过现在看这篇文章,不免觉得反倒觉得当时有点幼稚。这几点又看到一段话,觉得挺好,幼稚地再贴一次:

人会长大三次。第一次是在发现自己不是世界中心的时候。第二次是在发现即使再怎么努力,终究还是有些事令人无能为力的时候。第三次是在,明知道有些事可能会无能为力,但还是会尽力争取的时候。

继续阅读人会长大三次

Linux添加FTP用户并设置权限

在linux中添加ftp用户,并设置相应的权限,操作步骤如下:

1、环境:ftp为vsftp。被限制用户名为test。被限制路径为/home/test

2、建用户,命令行状态下,在root用户下:
运行命令:“useradd -d /home/test test”  //增加用户test,并制定test用户的主目录为/home/test
运行命令:“passwd test”  //为test设置密码,运行后输入两次相同密码

3、更改用户相应的权限设置:
运行命令:“usermod -s /sbin/nologin test”  //限定用户test不能telnet,只能ftp
运行命令:“usermod -s /sbin/bash test”  //用户test恢复正常
运行命令:“usermod -d /test test”  //更改用户test的主目录为/test

4、限制用户只能访问/home/test,不能访问其他路径
修改/etc/vsftpd/vsftpd.conf如下:
chroot_list_enable=YES
# (default follows)
chroot_list_file=/etc/vsftpd/chroot_list

编辑上面的内容

第一行:chroot_list_enable=YES  //限制访问自身目录
第三行:编辑chroot_list。根据第三行说指定的目录,找到chroot_list文件。(因主机不同,文件名也许略有不同)
编辑chroot_list,将受限制的用户添加进去,每个用户名一行

5、重启服务器
改完配置文件,不要忘记重启vsFTPd服务器
运行命令:/etc/init.d/vsftpd restart

6、如果需要允许用户修改密码,但是又没有telnet登录系统的权限:
运行命令:“usermod -s /usr/bin/passwd test”  //用户telnet后将直接进入改密界面

PHP的网站主要攻击方式有哪些?

1、命令注入(Command Injection)

2、eval注入(Eval Injection)

3、客户端脚本攻击(Script Insertion)

4、跨网站脚本攻击(Cross Site Scripting, XSS)
http://www.cnblogs.com/bangerlee/archive/2013/04/06/3002142.html

5、SQL注入攻击(SQL injection)

6、跨网站请求伪造攻击(Cross Site Request Forgeries, CSRF)
http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html

7、Session 会话劫持(Session Hijacking)

8、Session 固定攻击(Session Fixation)

9、HTTP响应拆分攻击(HTTP Response Splitting)

10、文件上传漏洞(File Upload Attack)

11、目录穿越漏洞(Directory Traversal)

12、远程文件包含攻击(Remote Inclusion)

13、动态函数注入攻击(Dynamic Variable Evaluation)

14、URL攻击(URL attack)

15、表单提交欺骗攻击(Spoofed Form Submissions)

16、HTTP请求欺骗攻击(Spoofed HTTP Requests)

怎么构建高性能WEB站点

1.时间都花在哪里了:

(1)数据在网络上的传输时间。

(2)服务端处理请求,并生成返回数据的时间。

(3)浏览器本地计算与渲染的时间。

2.瓶颈在哪里,找到问题的本质及原理?

3.调优方案:

(1)增加带宽。

(2)减少网页中的HTTP请求。

(3)加快服务端脚本的计算速度(解析器优化)。

(4)动态内容缓存。

(5)数据缓存。

(6)动态内容静态化。

(7)web服务器软件的选择与配置。

(8)服务器资源的分开部署,CDN加速。

(9)集群与负载均衡。

(10)数据库优化:

【1】连接池

【2】表结构,索引(explain、慢查询日志)

【3】合理选择数据库引擎

【4】海量数据时,考虑垂直切割数据库,增加冗余并分散数据存放。

(11)增加资源来提高性能。

4.优化产品体验减少等待的感觉。

PHP,Mysql-根据一个给定经纬度的点,进行附近地点查询

目前的工作是需要对用户的一些数据进行分析,每个用户都有若干条记录,每条记录中有用户的一个位置,是用经度和纬度表示的。
还有一个给定的数据库,存储的是一些已知地点以及他们的经纬度,内有43W多条的数据。
现在需要拿用户的经纬度和已知地点进行距离匹配,如果它们之间的距离小于一定的数据,比如说500米,就认为用户是在这个地点。
MYSQL本身是支持空间索引的,但是在5.x的版本中,取消了对Distance()和Related()的支持,参考这里:MySQL 5.1参考手册 :: 19. 中的空间扩展 19.5.6. 测试几何类之间空间关系的函数,无法使用空间的距离函数去直接去查询距离在一定范围内的点。所以,我首先想到的是,对每条记录,去进行遍历,跟数据库中的每一个点进行距离计算,当距离小于500米时,认为匹配。这样做确实能够得到结果,但是效率极其低下,因为每条记录都要去循环匹配40W条数据,其消耗的时间可想而知。经过记录,发现每条记录处理的时间消耗达到1700ms,针对每天上亿的数据量,这样一个处理速度,让人情何以堪啊。。。
我自己也有个想法,就是找到每条记录所在点的经纬度周围的一个大概范围,比方说正方形的四个点,然后使用mysql的空间计算,使用MBR去得出点在这个矩形内的已知记录,然后进行匹配。可惜,自己没想出能计算到四个点经纬度的方法。
意外的,查询到了一个关于这个计算附近地点搜索初探,里面使用python实现了这个想法。
所以参考了一下原文中的算法,使用PHP进行了实现。实现原理也是很相似的,先算出该点周围的矩形的四个点,然后使用经纬度去直接匹配数据库中的记录。

20120615-php-mysql-earth-distance-map

参考wiki百科上的一些球面计算公式:

假设已知点的经纬度分别为$lng, $lat
先实现经度范围的查询,
在haversin公式中令φ1 = φ2,可得:

20120615-haversin-distance-lng

PHP进行计算,就是:

//$lat 已知点的纬度
$dlng = 2 * asin(sin($distance / (2 * EARTH_RADIUS)) / cos(deg2rad($lat)));
$dlng = rad2deg($dlng);//转换弧度

然后是纬度范围的查询,
在haversin公式中令 Δλ = 0,可得

20120615-haversin-distance-lat

在PHP中进行计算,就是:

$dlat = $distance/EARTH_RADIUS;//EARTH_RADIUS地球半径
$dlat = rad2deg($dlat);//转换弧度

最后,就可以得出四个点的坐标:
left-top : (lat + dlat, lng – dlng)
right-top : (lat + dlat, lng + dlng)
left-bottom : (lat – dlat, lng – dlng)
right-bottom: (lat – dlat, lng + dlng)

我把以上方法写成了一个函数,综合起来就是:

 define(EARTH_RADIUS, 6371);//地球半径,平均半径为6371km
 /**
 *计算某个经纬度的周围某段距离的正方形的四个点
 *
 *@param lng float 经度
 *@param lat float 纬度
 *@param distance float 该点所在圆的半径,该圆与此正方形内切,默认值为0.5千米
 *@return array 正方形的四个点的经纬度坐标
 */
 function returnSquarePoint($lng, $lat,$distance = 0.5){
	$dlng =  2 * asin(sin($distance / (2 * EARTH_RADIUS)) / cos(deg2rad($lat)));
	$dlng = rad2deg($dlng);
	$dlat = $distance/EARTH_RADIUS;
	$dlat = rad2deg($dlat);
	return array(
	   'left-top'=>array('lat'=>$lat + $dlat,'lng'=>$lng-$dlng),
	   'right-top'=>array('lat'=>$lat + $dlat, 'lng'=>$lng + $dlng),
	   'left-bottom'=>array('lat'=>$lat - $dlat, 'lng'=>$lng - $dlng),
	   'right-bottom'=>array('lat'=>$lat - $dlat, 'lng'=>$lng + $dlng)
	);
 }
//使用此函数计算得到结果后,带入sql查询。
$squares = returnSquarePoint($lng, $lat);
$info_sql = "select id,locateinfo,lat,lng from `lbs_info` where lat<>0 and lat>{$squares['right-bottom']['lat']} and lat<{$squares['left-top']['lat']} and lng>{$squares['left-top']['lng']} and lng<{$squares['right-bottom']['lng']} ";

在lat和lng上建立一个联合索引后,使用此项查询,每条记录的查询消耗平均为0.8毫秒,相比以前的1700ms,真的是天壤之别啊。效率真真的是以前的2125倍~~

总结:这应该也不是效率最好的办法,但是效率比以前确实有明显的提升。请记住,总有办法更好的。

转自 http://digdeeply.org/archives/06152067.html

MySql如何一次更新多条数据(不建议使用UPDATE语句)

我们知道当插入多条数据的时候insert支持多条语句:

INSERT INTO t_member (id, name, email) VALUES
    (1, 'nick', 'nick@126.com'),
    (4, 'angel','angel@163.com'),
    (7, 'brank','ba198@126.com');

但是对于更新记录,由于update语法不支持一次更新多条记录,只能一条一条执行:

UPDATE t_member SET name='nick', email='nick@126.com' WHERE id=1;
UPDATE t_member SET name='angel', email='angel@163.com' WHERE id=4;
UPDATE t_member SET name='brank', email='ba198@126.com' WHERE id=7;

这里问题就出现了,倘若这个update list非常大时(譬如说5000条),这个执行率可想而知。

这就要介绍一下在MySql中INSERT语法具有一个条件DUPLICATE KEY UPDATE,这个语法和适合用在需要判断记录是否存在,不存在则插入存在则更新的记录。

具体的语法可以参见:http://dev.mysql.com/doc/refman/5.0/en/insert.html

基于上面这种情况,针对更新记录,仍然使用insert语句,不过限制主键重复时,更新字段。如下:

INSERT INTO t_member (id, name, email) VALUES
    (1, 'nick', 'nick@126.com'),
    (4, 'angel','angel@163.com'),
    (7, 'brank','ba198@126.com')
ON DUPLICATE KEY UPDATE name=VALUES(name), email=VALUES(email);

注意:ON DUPLICATE KEY UPDATE只是MySQL的特有语法,并不是SQL标准语法!

原文地址:MySql更新多条数据不建议使用UPDATE语句, 感谢原作者分享。

Cookie禁用了,Session还能用吗?

Cookie与 Session,一般认为是两个独立的东西,Session采用的是在服务器端保持状态的方案,而Cookie采用的是在客户端保持状态的方案。但为什么禁用Cookie就不能得到Session呢?因为Session是用Session ID来确定当前对话所对应的服务器Session,而Session ID是通过Cookie来传递的,禁用Cookie相当于失去了Session ID,也就得不到Session了。

是不是Cookie让禁用了,Session就一定不能用了呢?在PHP中,通过相关的配置,可以让Session不依赖Cookie而存在。这是因为:

Session,储存于服务器端(默认以文件方式存储Session),根据客户端提供的Session ID来得到用户的文件,取得变量的值,Session ID可以使用客户端的Cookie或者Http1.1协议的Query_String(就是访问的URL的“?”后面的部分)来传送给服务器,然后服务器读取Session的目录……。也就是说,Session ID是取得存储在服务上的Session变量的身份证。当代码session_start();运行的时候,就在服务器上产生了一个Session文件,随之也产生了与之唯一对应的一个Session ID,定义Session变量以一定形式存储在刚才产生的Session文件中。通过Session ID,可以取出定义的变量。跨页后,为了使用Session,你必须又执行session_start();将又会产生一个Session文件,与之对应产生相应的Session ID,用这个session id是取不出前面提到的第一个Session文件中的变量的,因为这个Session ID不是打开它的“钥匙”。如果在session_start();之前加代码session_id($session id);将不产生新的Session文件,直接读取与这个id对应的Session文件。

PHP中的Session在默认情况下是使用客户端的Cookie来保存Session ID的,所以当客户端的cookie出现问题的时候就会影响Session了。必须注意的是:Session不一定必须依赖Cookie,这也是Session相比Cookie的高明之处。当客户端的Cookie被禁用或出现问题时,PHP会自动把Session ID附着在URL中,这样再通过Session ID就能跨页使用Session变量了。但这种附着也是有一定条件的,即“php.ini中的session.use_trans_sid = 1“,或者编译时打开打开了“–enable-trans-sid”选项。

用过论坛的朋友都知道,在进入论坛的时候,往往会提示你检查Cookie是否打开,这是因为大多数论坛都是基于Cookie的,论坛用它来保存用户名、密码等用户信息,方便使用。而且很多朋友都认为Cookie不安全(其实不是这样),往往禁用它。其实在PHP程序中,我们完全可以用Session来代替Cookie,它可以不依赖于客户端是否开启Cookie。

所以,我们可以抛开Cookie使用Session,即假定用户关闭Cookie的情况下使用Session,其实现途径有以下几种:

1. 设置php.ini配置文件中的“session.use_trans_sid = 1”,或者编译时打开打开了“–enable-trans-sid”选项,让PHP自动跨页传递Session ID。
2. 手动通过URL传值、隐藏表单传递Session ID。
3. 用文件、数据库等形式保存Session ID,在跨页过程中手动调用。

手机APP扫码登录PC端网站

PC端的微信、淘宝、微博都相继推出了通过客户端扫码登录,感觉很创新;我想了一个通过微信公众帐号登录雅酷网的流程,自己瞎想的

1、用户在微信公众帐号绑定自己的微信和网站账户

2、用户在网站选择微信登录,后台记录页面一个cookie,并生成一个6位随机数

3、用户在网站的微信公众帐号发送“随机密码”,返回上面生成的随机数

4、用户在网站输入随机数,后台比对当面页面这个cookie和随机数,验证成功则登录成功

另外一种更简单的操作思路(更类似于扫码登录):

1、用户在微信公众帐号绑定自己的微信和网站账户 2、用户在网站选择微信登录,后台记录页面一个cookie,并生成一个6位随机数且显示给用户,同时不断监听后台 3、用户在网站的微信公众帐号发送上面生成的随机数,后台比对这个页面cookie和收到的随机数是否正确,正确则返回给PC端,PC端自动登录

微信扫描二维码登录网页版原理

CSC模式为:web客户端 –> 服务端

1、打开微信网页版,在浏览器生成一个web客户端,此客户端并未任务授权,但服务端给它生成了一个唯一标识码UUID,监听服务端登录请求;

2、手机客户端点击 [登录网页版] 时,实际上此时客户端是登录了且有访问授权码 access_token,扫描网页二维码,获得UUID,将access_token 与UUID编码后,传自腾讯服务端,服务端生成登录授权码,通知正在监听中的网页客户端;

3、网页客户端通过侦听器获得授权码,往服务器请求用户信息,完成登录过程。

来往网页版扫码自动登录的实现原理

1、每打开一次页面的时候会随机生成一个含有唯一ID的二维码;

2、当用户使用登陆后的来往扫描该二维码的时候,客户端会解析出二维码中的这个唯一ID会将这个id和手机上的来往账号及密码绑定,并上传到服务器;

3、来往网页版页面每隔1秒或2秒会get请求该id对应的来往账号及密码,如果id绑定上了来往账号和密码,那么就可以请求到账号和密码,就可以自动登录了。

4、这样实现的目的1.安全,用户不需要再次输出用户名密码,2.方便,用户不需要再次输出用户名密码.3.比如QQ与手机图片互传也是这样一个原理.

我们在实践中可以这样操作:
0、前提是APP上登录了帐号,有user_id,需要用这个登录的帐号里的扫二维码的功能扫PC上的一个有二维码网页
1、PC上的有二维码带一个uuid的随机数,网页用js写一个定时任务,每秒向后台发起一个ajax请求,把这个uuid传给后台,后台看看数据库里这个uuid是否有对应的user_id。
2、APP上扫码时,获取扫到的二维码里的uuid,并把uuid和user_id传给后台,后台把uuid和user_id对应到数据库里
3、uuid和user_id对应到数据库后,步骤1中ajax请求就会发现uuid已经可以对应到user_id了,自动写入session等,让这个user_id在PC上是登录状态,并跳转到登录后的页面。

另外,从安全、性能上考虑要注意
1、uuid应该有有效期之类的,比如每30秒过期自动更新二维码,登录后把uuid失效
2、存储到mysql数据库里不一定合适,因为数据量很大,而且都是临时性的数据,可以考虑把uuid存储到redis或memcache里

php读取同服务器中的php源代码

比如我有两个文件a.php,b.php。

a.php文件中的语句是:
<?php
echo “i am a.php”;
?>

现在,我需要在b.php文件显示文件a.php中的源代码,是源代码,如下:

<?php
$a_code = file_get_contents(‘a.php’);
echo htmlspecialchars($a_code);
?>

重点即在此htmlspecialchars()函数,htmlspecialchars() 函数把一些预定义的字符转换为 HTML 实体。