专业名词

专业名词

Linux上如何查找文件里含有特定字符串?

回复

工具软件zkbhj 回复了问题 • 1 人关注 • 1 个回复 • 40 次浏览 • 2019-02-27 16:11 • 来自相关话题

#自学课程#《放学你别走第一季之GO语言学习》Day1打卡

GoLangzkbhj 发表了文章 • 0 个评论 • 36 次浏览 • 2019-02-22 14:53 • 来自相关话题

【Day1任务】
熟悉Go编程语言,搭建运行环境,选择适合自己的IDE,并写出自己的第一个GO程序(hello world!),并用命令形式成功运行。
打卡时间:明天(2月21日)18:30
打卡形式:程序运行截图+现场面对面讨论package main

import "fmt"

func main(){
fmt.Printf("%s\n","Hello wolrd!This is my first go program!I'm ZhengKai!")
} 查看全部
【Day1任务】
熟悉Go编程语言,搭建运行环境,选择适合自己的IDE,并写出自己的第一个GO程序(hello world!),并用命令形式成功运行。
打卡时间:明天(2月21日)18:30
打卡形式:程序运行截图+现场面对面讨论
package main

import "fmt"

func main(){
fmt.Printf("%s\n","Hello wolrd!This is my first go program!I'm ZhengKai!")
}

两种数据序列化方案性能对比:Msgpack和Json

专业名词zkbhj 发表了文章 • 0 个评论 • 105 次浏览 • 2019-01-23 11:00 • 来自相关话题

    MessagePack(简写msgpack)是一个高效的二进制序列化格式。它让你像JSON一样可以在各种语言之间交换数据。但是它比JSON更快、更小。小的整数会被编码成一个字节,短的字符串仅仅只需要比它的长度多一字节的大小。之前在lua脚本中使用过msgpack,因为有大量数据要入redis,而考虑到内存开销,使用了压缩比更大的msgpack。因为msgpack是一个二进制格式,所以没法像json后的字符串一样可直观地查看数据。
 
    msgpack的官网地址:http://pecl.php.net/package/msgpack 里面有各PHP版本windows下的dll扩展,也有源码包供linux下编译,所以像lua这样的脚本语言可以直接使用。msgpack和json_encode都是序列化存储数据,那么msgpack的效率与json的效率相比的话到底怎么样呢?看下面这个简单的对比程序:
//msgpack与json的性能对比
//1,数据拼凑
$data =array(
'youku' => '优酷视频', 'pptv' => 'PPTV', 'sohu' => '搜狐视频', 'qiyi' => '奇艺视频', 'letv' => '乐视视频',
'tencent' => '腾讯视频', 'sina' => '新浪视频', 'tudou' => '土豆视频', 'm1905' => '电影网', 'cntv' => 'CNTV',
);
$data = json_encode($data);
$newArr = array();
for($i = 1; $i<=500; $i++) //修改此处$i的最大值以控制数据的大小
{
$newArr [] =$data;
}

//数据大小对比
$msg_data = msgpack_pack($newArr);
echo "使用msgpack处理后大小:".strlen($msg_data);
$json_data = json_encode($newArr);
echo "<br>使用json处理后大小:".strlen($json_data);
echo "<br>msgpack处理后大小与json处理后大小比为1:".round((strlen($json_data)/strlen($msg_data)),2);

//计算1000次msgpack压缩用时
$time = microtime(true);
for($i = 1; $i<1000; $i++){
msgpack_pack($newArr);
}
echo '<br>1000次msgpack操作用时:'.(microtime(true)- $time);

//计算1000次json_encode压缩用时
$time1 = microtime(true);
for($i = 1; $i<1000; $i++){
json_encode($newArr);
}
echo '<br>1000次json_encode操作用时:'.(microtime(true)- $time1); 程序过程没什么可说的了,就是先拼凑了一个数组数据(用$i来控制它的大小)。然后对比对这个数组的处理用时,如果$i很小,假如为2,得到的结果如下:
使用msgpack处理后大小:609
使用json处理后大小:751
msgpack处理后大小与json处理后大小比为1:1.23
1000次msgpack操作用时:0.05400013923645
1000次json_encode操作用时:0.03600001335144 从上面的结果来看,msg_pack的效率根本不如json_encode的效率,只是msg_pack的压缩率大些而已。而当我把$i改大点,比如改到500后,结果就完全反转了:
使用msgpack处理后大小:152003
使用json处理后大小:187501
msgpack处理后大小与json处理后大小比为1:1.23
1000次msgpack操作用时:0.68599987030029
1000次json_encode操作用时:2.2000000476837     经过多次测试,最后做两个总结如下:    1,msg_pack的压缩效率比json_encode大是毫无疑问,但压缩比我这只看到提高了20%左右,可能和数据类型有关系,这个值只供参考。


    2,在数据量较小的情况下,msg_pack的效率不如json_encode.而在数据量较大时,msg_pack的效率就远大于json_encode。

    3,和数据序列化一样,对数据的反序列化上,也是数量量大时,msg_unpack的效率远大于json_decode.

    下面是进行反序列化时的结果:
1000次msgpack操作用时:0.80399990081787
1000次json_encode操作用时:2.6389999389648 查看全部
    MessagePack(简写msgpack)是一个高效的二进制序列化格式。它让你像JSON一样可以在各种语言之间交换数据。但是它比JSON更快、更小。小的整数会被编码成一个字节,短的字符串仅仅只需要比它的长度多一字节的大小。之前在lua脚本中使用过msgpack,因为有大量数据要入redis,而考虑到内存开销,使用了压缩比更大的msgpack。因为msgpack是一个二进制格式,所以没法像json后的字符串一样可直观地查看数据。
 
    msgpack的官网地址:http://pecl.php.net/package/msgpack 里面有各PHP版本windows下的dll扩展,也有源码包供linux下编译,所以像lua这样的脚本语言可以直接使用。msgpack和json_encode都是序列化存储数据,那么msgpack的效率与json的效率相比的话到底怎么样呢?看下面这个简单的对比程序:
//msgpack与json的性能对比
//1,数据拼凑
$data =array(
'youku' => '优酷视频', 'pptv' => 'PPTV', 'sohu' => '搜狐视频', 'qiyi' => '奇艺视频', 'letv' => '乐视视频',
'tencent' => '腾讯视频', 'sina' => '新浪视频', 'tudou' => '土豆视频', 'm1905' => '电影网', 'cntv' => 'CNTV',
);
$data = json_encode($data);
$newArr = array();
for($i = 1; $i<=500; $i++) //修改此处$i的最大值以控制数据的大小
{
$newArr [] =$data;
}

//数据大小对比
$msg_data = msgpack_pack($newArr);
echo "使用msgpack处理后大小:".strlen($msg_data);
$json_data = json_encode($newArr);
echo "<br>使用json处理后大小:".strlen($json_data);
echo "<br>msgpack处理后大小与json处理后大小比为1:".round((strlen($json_data)/strlen($msg_data)),2);

//计算1000次msgpack压缩用时
$time = microtime(true);
for($i = 1; $i<1000; $i++){
msgpack_pack($newArr);
}
echo '<br>1000次msgpack操作用时:'.(microtime(true)- $time);

//计算1000次json_encode压缩用时
$time1 = microtime(true);
for($i = 1; $i<1000; $i++){
json_encode($newArr);
}
echo '<br>1000次json_encode操作用时:'.(microtime(true)- $time1);
 程序过程没什么可说的了,就是先拼凑了一个数组数据(用$i来控制它的大小)。然后对比对这个数组的处理用时,如果$i很小,假如为2,得到的结果如下:
使用msgpack处理后大小:609
使用json处理后大小:751
msgpack处理后大小与json处理后大小比为1:1.23
1000次msgpack操作用时:0.05400013923645
1000次json_encode操作用时:0.03600001335144
 从上面的结果来看,msg_pack的效率根本不如json_encode的效率,只是msg_pack的压缩率大些而已。而当我把$i改大点,比如改到500后,结果就完全反转了:
使用msgpack处理后大小:152003
使用json处理后大小:187501
msgpack处理后大小与json处理后大小比为1:1.23
1000次msgpack操作用时:0.68599987030029
1000次json_encode操作用时:2.2000000476837
     经过多次测试,最后做两个总结如下:    1,msg_pack的压缩效率比json_encode大是毫无疑问,但压缩比我这只看到提高了20%左右,可能和数据类型有关系,这个值只供参考。


    2,在数据量较小的情况下,msg_pack的效率不如json_encode.而在数据量较大时,msg_pack的效率就远大于json_encode。

    3,和数据序列化一样,对数据的反序列化上,也是数量量大时,msg_unpack的效率远大于json_decode.

    下面是进行反序列化时的结果:
1000次msgpack操作用时:0.80399990081787
1000次json_encode操作用时:2.6389999389648

PHP如何运行时设置错误报告输出到页面上?

回复

PHPzkbhj 回复了问题 • 1 人关注 • 1 个回复 • 130 次浏览 • 2018-11-21 14:35 • 来自相关话题

橘子和橙子有什么区别?分别用英语怎么说?

回复

常识zkbhj 回复了问题 • 1 人关注 • 1 个回复 • 279 次浏览 • 2018-11-16 12:59 • 来自相关话题

HTTP中有哪些方法可供使用?

回复

网络zkbhj 回复了问题 • 1 人关注 • 1 个回复 • 94 次浏览 • 2018-11-14 16:41 • 来自相关话题

安全领域提到的payload是指什么?

回复

专业名词zkbhj 回复了问题 • 1 人关注 • 1 个回复 • 164 次浏览 • 2018-11-13 17:02 • 来自相关话题

一点点学习Linux:如何添加crontab计划任务?

服务器zkbhj 发表了文章 • 0 个评论 • 84 次浏览 • 2018-11-13 11:53 • 来自相关话题

crond 是linux用来定期执行程序的命令。当安装完成操作系统之后,默认便会启动此任务调度命令。crond命令每分锺会定期检查是否有要执行的工作,如果有要执行的工作便会自动执行该工作。可以用以下的方法启动、关闭这个服务:
/sbin/service crond start //启动服务

/sbin/service crond stop //关闭服务

/sbin/service crond restart //重启服务

/sbin/service crond reload //重新载入配置1.linux任务调度的工作主要分为以下两类:

系统执行的工作:系统周期性所要执行的工作,如备份系统数据、清理缓存

个人执行的工作:某个用户定期要做的工作,例如每隔10分钟检查邮件服务器是否有新信,这些工作可由每个用户自行设置。


2.crontab命令选项:

cron服务提供crontab命令来设定cron服务的,以下是这个命令的一些参数与说明:

crontab -u //设定某个用户的cron服务,一般root用户在执行这个命令的时候需要此参数

crontab -l //列出某个用户cron服务的详细内容

crontab -r //删除某个用户的cron服务

crontab -e //编辑某个用户的cron服务

比如说root查看自己的cron设置:crontab -u root -l

再例如,root想删除fred的cron设置:crontab -u fred -r

在编辑cron服务时,编辑的内容有一些格式和约定,输入:crontab -u root -e

进入vi编辑模式,编辑的内容一定要符合下面的格式:*/1 * * * * ls >> /tmp/ls.txt

3.cron文件语法 分 小时 日 月 星期 命令

0-59 0-23 1-31 1-12 0-6 command (取值范围,0表示周日一般一行对应一个任务)4.记住几个特殊符号的含义:

"*"代表取值范围内的数字,

"/"代表"每",

"-"代表从某个数字到某个数字,

","分开几个离散的数字
 
5.举几个例子
5 * * * * ls //指定每小时的第5分钟执行一次ls命令

30 5 * * * ls //指定每天的 5:30 执行ls命令

30 7 8 * * ls //指定每月8号的7:30分执行ls命令

30 5 8 6 * ls //指定每年的6月8日5:30执行ls命令

30 6 * * 0 ls //指定每星期日的6:30执行ls命令[注:0表示星期天,1表示星期1,以此类推,也可以用英文来表示,sun表示星期天,mon表示星期一等。]

30 3 10,20 * * ls //每月10号及20号的3:30执行ls命令[注:”,”用来连接多个不连续的时段]

25 8-11 * * * ls //每天8-11点的第25分钟执行ls命令[注:”-”用来连接连续的时段]

*/15 * * * * ls //每15分钟执行一次ls命令 [即每个小时的第0 15 30 45 60分钟执行ls命令 ]

30 6 */10 * * ls //每个月中,每隔10天6:30执行一次ls命令[即每月的1、11、21、31日是的6:30执行一次ls命令。 ]

50 7 * * * root run-parts /etc/cron.daily //每天7:50以root 身份执行/etc/cron.daily目录中的所有可执行文件[ 注:run-parts参数表示,执行后面目录中的所有可执行文件。 ]6.新增调度任务可用两种方法:

a.在命令行输入: crontab -e 然后添加相应的任务,wq存盘退出。

b.直接编辑/etc/crontab 文件,即vi /etc/crontab,添加相应的任务。 查看全部
crond 是linux用来定期执行程序的命令。当安装完成操作系统之后,默认便会启动此任务调度命令。crond命令每分锺会定期检查是否有要执行的工作,如果有要执行的工作便会自动执行该工作。可以用以下的方法启动、关闭这个服务:
/sbin/service crond start //启动服务

/sbin/service crond stop //关闭服务

/sbin/service crond restart //重启服务

/sbin/service crond reload //重新载入配置
1.linux任务调度的工作主要分为以下两类:


系统执行的工作:系统周期性所要执行的工作,如备份系统数据、清理缓存

个人执行的工作:某个用户定期要做的工作,例如每隔10分钟检查邮件服务器是否有新信,这些工作可由每个用户自行设置。



2.crontab命令选项:

cron服务提供crontab命令来设定cron服务的,以下是这个命令的一些参数与说明:

crontab -u //设定某个用户的cron服务,一般root用户在执行这个命令的时候需要此参数

crontab -l //列出某个用户cron服务的详细内容

crontab -r //删除某个用户的cron服务

crontab -e //编辑某个用户的cron服务

比如说root查看自己的cron设置:crontab -u root -l

再例如,root想删除fred的cron设置:crontab -u fred -r

在编辑cron服务时,编辑的内容有一些格式和约定,输入:crontab -u root -e

进入vi编辑模式,编辑的内容一定要符合下面的格式:*/1 * * * * ls >> /tmp/ls.txt

3.cron文件语法
  分     小时      日       月       星期      命令

0-59 0-23 1-31 1-12 0-6 command (取值范围,0表示周日一般一行对应一个任务)
4.记住几个特殊符号的含义:

"*"代表取值范围内的数字,

"/"代表"每",

"-"代表从某个数字到某个数字,

","分开几个离散的数字
 
5.举几个例子
5       *       *       *      *     ls              //指定每小时的第5分钟执行一次ls命令

30 5 * * * ls //指定每天的 5:30 执行ls命令

30 7 8 * * ls //指定每月8号的7:30分执行ls命令

30 5 8 6 * ls //指定每年的6月8日5:30执行ls命令

30 6 * * 0 ls //指定每星期日的6:30执行ls命令[注:0表示星期天,1表示星期1,以此类推,也可以用英文来表示,sun表示星期天,mon表示星期一等。]

30 3 10,20 * * ls //每月10号及20号的3:30执行ls命令[注:”,”用来连接多个不连续的时段]

25 8-11 * * * ls //每天8-11点的第25分钟执行ls命令[注:”-”用来连接连续的时段]

*/15 * * * * ls //每15分钟执行一次ls命令 [即每个小时的第0 15 30 45 60分钟执行ls命令 ]

30 6 */10 * * ls //每个月中,每隔10天6:30执行一次ls命令[即每月的1、11、21、31日是的6:30执行一次ls命令。 ]

50 7 * * * root run-parts /etc/cron.daily //每天7:50以root 身份执行/etc/cron.daily目录中的所有可执行文件[ 注:run-parts参数表示,执行后面目录中的所有可执行文件。 ]
6.新增调度任务可用两种方法:

a.在命令行输入: crontab -e 然后添加相应的任务,wq存盘退出。

b.直接编辑/etc/crontab 文件,即vi /etc/crontab,添加相应的任务。

类设计的六大基本原则

架构思想zkbhj 发表了文章 • 0 个评论 • 80 次浏览 • 2018-11-12 20:12 • 来自相关话题

一.单一职责原则

Single Responsibility Principle, 简称SRP。

定义:There should never be more than one reason for a class to change.

应该有且仅有一个原因引起类的变更。
 
二.里氏替换原则

Liskov Substitution Principle, 简称LSP。

定义:Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

(所有引用基类的地方必须能透明地使用其子类的对象)
 
三.依赖倒置原则

Dependence Inversion Principle, 简称DIP

定义:High level modules should not depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details.Details should depend upon abstractions.

翻译过来,包含三层含义:

1.高层模块不应该依赖低层模块,两者都应该依赖其抽象。2.抽象不应该依赖细节。3.细节应该依赖抽象。

精简的定义: 面向接口编程。
 
四.接口隔离原则:
接口--这里指用interface关键字定义的接口。
定义:
1.Clients should not be forced to depend upon interfaces that they don't use.(客户端不应该依赖它不需要的接口)
2.The dependency of one class to anther one should depend on the smallest possible interface.(类间的依赖关系应该建立在最小的接口上)

概括:建立单一接口,不要建立臃肿庞大的接口。通俗来讲:接口尽量细化,同时接口中的方法尽量少。
 
五.迪米特法则
Law of Demeter, LOD。又称最少知识原则(Least Knowledge Principle, LKP)。
通俗来讲:一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我没有关系,那是你的事情,我就调用你提供的public方法,其他一概不关心。
 
六.开闭原则
Software entities like classes, modules and functions should be open for extension but closed for modifications.(一个软件实体如类、模块和函数应该对扩展开放,对修改关闭) 查看全部
一.单一职责原则

Single Responsibility Principle, 简称SRP。

定义:There should never be more than one reason for a class to change.

应该有且仅有一个原因引起类的变更。
 
二.里氏替换原则

Liskov Substitution Principle, 简称LSP。

定义:Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

(所有引用基类的地方必须能透明地使用其子类的对象)
 
三.依赖倒置原则

Dependence Inversion Principle, 简称DIP

定义:High level modules should not depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details.Details should depend upon abstractions.

翻译过来,包含三层含义:

1.高层模块不应该依赖低层模块,两者都应该依赖其抽象。2.抽象不应该依赖细节。3.细节应该依赖抽象。

精简的定义: 面向接口编程。
 
四.接口隔离原则:
接口--这里指用interface关键字定义的接口。
定义:
1.Clients should not be forced to depend upon interfaces that they don't use.(客户端不应该依赖它不需要的接口)
2.The dependency of one class to anther one should depend on the smallest possible interface.(类间的依赖关系应该建立在最小的接口上)

概括:建立单一接口,不要建立臃肿庞大的接口。通俗来讲:接口尽量细化,同时接口中的方法尽量少。
 
五.迪米特法则
Law of Demeter, LOD。又称最少知识原则(Least Knowledge Principle, LKP)。
通俗来讲:一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我没有关系,那是你的事情,我就调用你提供的public方法,其他一概不关心。
 
六.开闭原则
Software entities like classes, modules and functions should be open for extension but closed for modifications.(一个软件实体如类、模块和函数应该对扩展开放,对修改关闭)

经常看到有些商品上面有执行标准,GB和SB有什么区别?

回复

常识zkbhj 回复了问题 • 1 人关注 • 1 个回复 • 527 次浏览 • 2018-10-23 14:23 • 来自相关话题

Linux上如何查找文件里含有特定字符串?

回复

工具软件zkbhj 回复了问题 • 1 人关注 • 1 个回复 • 40 次浏览 • 2019-02-27 16:11 • 来自相关话题

PHP如何运行时设置错误报告输出到页面上?

回复

PHPzkbhj 回复了问题 • 1 人关注 • 1 个回复 • 130 次浏览 • 2018-11-21 14:35 • 来自相关话题

橘子和橙子有什么区别?分别用英语怎么说?

回复

常识zkbhj 回复了问题 • 1 人关注 • 1 个回复 • 279 次浏览 • 2018-11-16 12:59 • 来自相关话题

HTTP中有哪些方法可供使用?

回复

网络zkbhj 回复了问题 • 1 人关注 • 1 个回复 • 94 次浏览 • 2018-11-14 16:41 • 来自相关话题

安全领域提到的payload是指什么?

回复

专业名词zkbhj 回复了问题 • 1 人关注 • 1 个回复 • 164 次浏览 • 2018-11-13 17:02 • 来自相关话题

经常看到有些商品上面有执行标准,GB和SB有什么区别?

回复

常识zkbhj 回复了问题 • 1 人关注 • 1 个回复 • 527 次浏览 • 2018-10-23 14:23 • 来自相关话题

经常会遇到导出数据的需求,那么导出的Excel和CSV格式有什么区别呢?

回复

专业名词zkbhj 回复了问题 • 1 人关注 • 1 个回复 • 360 次浏览 • 2018-10-09 14:33 • 来自相关话题

今年22号台风“山竹”在澳门等级为十号风球,十号风球指的是什么?

回复

随手记zkbhj 回复了问题 • 1 人关注 • 1 个回复 • 427 次浏览 • 2018-09-16 23:06 • 来自相关话题

“银弹”指的是什么意思?

回复

专业名词zkbhj 回复了问题 • 1 人关注 • 1 个回复 • 270 次浏览 • 2018-09-09 20:49 • 来自相关话题

什么是SSRF攻击?

回复

专业名词zkbhj 回复了问题 • 1 人关注 • 1 个回复 • 275 次浏览 • 2018-08-08 15:14 • 来自相关话题

#自学课程#《放学你别走第一季之GO语言学习》Day1打卡

GoLangzkbhj 发表了文章 • 0 个评论 • 36 次浏览 • 2019-02-22 14:53 • 来自相关话题

【Day1任务】
熟悉Go编程语言,搭建运行环境,选择适合自己的IDE,并写出自己的第一个GO程序(hello world!),并用命令形式成功运行。
打卡时间:明天(2月21日)18:30
打卡形式:程序运行截图+现场面对面讨论package main

import "fmt"

func main(){
fmt.Printf("%s\n","Hello wolrd!This is my first go program!I'm ZhengKai!")
} 查看全部
【Day1任务】
熟悉Go编程语言,搭建运行环境,选择适合自己的IDE,并写出自己的第一个GO程序(hello world!),并用命令形式成功运行。
打卡时间:明天(2月21日)18:30
打卡形式:程序运行截图+现场面对面讨论
package main

import "fmt"

func main(){
fmt.Printf("%s\n","Hello wolrd!This is my first go program!I'm ZhengKai!")
}

两种数据序列化方案性能对比:Msgpack和Json

专业名词zkbhj 发表了文章 • 0 个评论 • 105 次浏览 • 2019-01-23 11:00 • 来自相关话题

    MessagePack(简写msgpack)是一个高效的二进制序列化格式。它让你像JSON一样可以在各种语言之间交换数据。但是它比JSON更快、更小。小的整数会被编码成一个字节,短的字符串仅仅只需要比它的长度多一字节的大小。之前在lua脚本中使用过msgpack,因为有大量数据要入redis,而考虑到内存开销,使用了压缩比更大的msgpack。因为msgpack是一个二进制格式,所以没法像json后的字符串一样可直观地查看数据。
 
    msgpack的官网地址:http://pecl.php.net/package/msgpack 里面有各PHP版本windows下的dll扩展,也有源码包供linux下编译,所以像lua这样的脚本语言可以直接使用。msgpack和json_encode都是序列化存储数据,那么msgpack的效率与json的效率相比的话到底怎么样呢?看下面这个简单的对比程序:
//msgpack与json的性能对比
//1,数据拼凑
$data =array(
'youku' => '优酷视频', 'pptv' => 'PPTV', 'sohu' => '搜狐视频', 'qiyi' => '奇艺视频', 'letv' => '乐视视频',
'tencent' => '腾讯视频', 'sina' => '新浪视频', 'tudou' => '土豆视频', 'm1905' => '电影网', 'cntv' => 'CNTV',
);
$data = json_encode($data);
$newArr = array();
for($i = 1; $i<=500; $i++) //修改此处$i的最大值以控制数据的大小
{
$newArr [] =$data;
}

//数据大小对比
$msg_data = msgpack_pack($newArr);
echo "使用msgpack处理后大小:".strlen($msg_data);
$json_data = json_encode($newArr);
echo "<br>使用json处理后大小:".strlen($json_data);
echo "<br>msgpack处理后大小与json处理后大小比为1:".round((strlen($json_data)/strlen($msg_data)),2);

//计算1000次msgpack压缩用时
$time = microtime(true);
for($i = 1; $i<1000; $i++){
msgpack_pack($newArr);
}
echo '<br>1000次msgpack操作用时:'.(microtime(true)- $time);

//计算1000次json_encode压缩用时
$time1 = microtime(true);
for($i = 1; $i<1000; $i++){
json_encode($newArr);
}
echo '<br>1000次json_encode操作用时:'.(microtime(true)- $time1); 程序过程没什么可说的了,就是先拼凑了一个数组数据(用$i来控制它的大小)。然后对比对这个数组的处理用时,如果$i很小,假如为2,得到的结果如下:
使用msgpack处理后大小:609
使用json处理后大小:751
msgpack处理后大小与json处理后大小比为1:1.23
1000次msgpack操作用时:0.05400013923645
1000次json_encode操作用时:0.03600001335144 从上面的结果来看,msg_pack的效率根本不如json_encode的效率,只是msg_pack的压缩率大些而已。而当我把$i改大点,比如改到500后,结果就完全反转了:
使用msgpack处理后大小:152003
使用json处理后大小:187501
msgpack处理后大小与json处理后大小比为1:1.23
1000次msgpack操作用时:0.68599987030029
1000次json_encode操作用时:2.2000000476837     经过多次测试,最后做两个总结如下:    1,msg_pack的压缩效率比json_encode大是毫无疑问,但压缩比我这只看到提高了20%左右,可能和数据类型有关系,这个值只供参考。


    2,在数据量较小的情况下,msg_pack的效率不如json_encode.而在数据量较大时,msg_pack的效率就远大于json_encode。

    3,和数据序列化一样,对数据的反序列化上,也是数量量大时,msg_unpack的效率远大于json_decode.

    下面是进行反序列化时的结果:
1000次msgpack操作用时:0.80399990081787
1000次json_encode操作用时:2.6389999389648 查看全部
    MessagePack(简写msgpack)是一个高效的二进制序列化格式。它让你像JSON一样可以在各种语言之间交换数据。但是它比JSON更快、更小。小的整数会被编码成一个字节,短的字符串仅仅只需要比它的长度多一字节的大小。之前在lua脚本中使用过msgpack,因为有大量数据要入redis,而考虑到内存开销,使用了压缩比更大的msgpack。因为msgpack是一个二进制格式,所以没法像json后的字符串一样可直观地查看数据。
 
    msgpack的官网地址:http://pecl.php.net/package/msgpack 里面有各PHP版本windows下的dll扩展,也有源码包供linux下编译,所以像lua这样的脚本语言可以直接使用。msgpack和json_encode都是序列化存储数据,那么msgpack的效率与json的效率相比的话到底怎么样呢?看下面这个简单的对比程序:
//msgpack与json的性能对比
//1,数据拼凑
$data =array(
'youku' => '优酷视频', 'pptv' => 'PPTV', 'sohu' => '搜狐视频', 'qiyi' => '奇艺视频', 'letv' => '乐视视频',
'tencent' => '腾讯视频', 'sina' => '新浪视频', 'tudou' => '土豆视频', 'm1905' => '电影网', 'cntv' => 'CNTV',
);
$data = json_encode($data);
$newArr = array();
for($i = 1; $i<=500; $i++) //修改此处$i的最大值以控制数据的大小
{
$newArr [] =$data;
}

//数据大小对比
$msg_data = msgpack_pack($newArr);
echo "使用msgpack处理后大小:".strlen($msg_data);
$json_data = json_encode($newArr);
echo "<br>使用json处理后大小:".strlen($json_data);
echo "<br>msgpack处理后大小与json处理后大小比为1:".round((strlen($json_data)/strlen($msg_data)),2);

//计算1000次msgpack压缩用时
$time = microtime(true);
for($i = 1; $i<1000; $i++){
msgpack_pack($newArr);
}
echo '<br>1000次msgpack操作用时:'.(microtime(true)- $time);

//计算1000次json_encode压缩用时
$time1 = microtime(true);
for($i = 1; $i<1000; $i++){
json_encode($newArr);
}
echo '<br>1000次json_encode操作用时:'.(microtime(true)- $time1);
 程序过程没什么可说的了,就是先拼凑了一个数组数据(用$i来控制它的大小)。然后对比对这个数组的处理用时,如果$i很小,假如为2,得到的结果如下:
使用msgpack处理后大小:609
使用json处理后大小:751
msgpack处理后大小与json处理后大小比为1:1.23
1000次msgpack操作用时:0.05400013923645
1000次json_encode操作用时:0.03600001335144
 从上面的结果来看,msg_pack的效率根本不如json_encode的效率,只是msg_pack的压缩率大些而已。而当我把$i改大点,比如改到500后,结果就完全反转了:
使用msgpack处理后大小:152003
使用json处理后大小:187501
msgpack处理后大小与json处理后大小比为1:1.23
1000次msgpack操作用时:0.68599987030029
1000次json_encode操作用时:2.2000000476837
     经过多次测试,最后做两个总结如下:    1,msg_pack的压缩效率比json_encode大是毫无疑问,但压缩比我这只看到提高了20%左右,可能和数据类型有关系,这个值只供参考。


    2,在数据量较小的情况下,msg_pack的效率不如json_encode.而在数据量较大时,msg_pack的效率就远大于json_encode。

    3,和数据序列化一样,对数据的反序列化上,也是数量量大时,msg_unpack的效率远大于json_decode.

    下面是进行反序列化时的结果:
1000次msgpack操作用时:0.80399990081787
1000次json_encode操作用时:2.6389999389648

一点点学习Linux:如何添加crontab计划任务?

服务器zkbhj 发表了文章 • 0 个评论 • 84 次浏览 • 2018-11-13 11:53 • 来自相关话题

crond 是linux用来定期执行程序的命令。当安装完成操作系统之后,默认便会启动此任务调度命令。crond命令每分锺会定期检查是否有要执行的工作,如果有要执行的工作便会自动执行该工作。可以用以下的方法启动、关闭这个服务:
/sbin/service crond start //启动服务

/sbin/service crond stop //关闭服务

/sbin/service crond restart //重启服务

/sbin/service crond reload //重新载入配置1.linux任务调度的工作主要分为以下两类:

系统执行的工作:系统周期性所要执行的工作,如备份系统数据、清理缓存

个人执行的工作:某个用户定期要做的工作,例如每隔10分钟检查邮件服务器是否有新信,这些工作可由每个用户自行设置。


2.crontab命令选项:

cron服务提供crontab命令来设定cron服务的,以下是这个命令的一些参数与说明:

crontab -u //设定某个用户的cron服务,一般root用户在执行这个命令的时候需要此参数

crontab -l //列出某个用户cron服务的详细内容

crontab -r //删除某个用户的cron服务

crontab -e //编辑某个用户的cron服务

比如说root查看自己的cron设置:crontab -u root -l

再例如,root想删除fred的cron设置:crontab -u fred -r

在编辑cron服务时,编辑的内容有一些格式和约定,输入:crontab -u root -e

进入vi编辑模式,编辑的内容一定要符合下面的格式:*/1 * * * * ls >> /tmp/ls.txt

3.cron文件语法 分 小时 日 月 星期 命令

0-59 0-23 1-31 1-12 0-6 command (取值范围,0表示周日一般一行对应一个任务)4.记住几个特殊符号的含义:

"*"代表取值范围内的数字,

"/"代表"每",

"-"代表从某个数字到某个数字,

","分开几个离散的数字
 
5.举几个例子
5 * * * * ls //指定每小时的第5分钟执行一次ls命令

30 5 * * * ls //指定每天的 5:30 执行ls命令

30 7 8 * * ls //指定每月8号的7:30分执行ls命令

30 5 8 6 * ls //指定每年的6月8日5:30执行ls命令

30 6 * * 0 ls //指定每星期日的6:30执行ls命令[注:0表示星期天,1表示星期1,以此类推,也可以用英文来表示,sun表示星期天,mon表示星期一等。]

30 3 10,20 * * ls //每月10号及20号的3:30执行ls命令[注:”,”用来连接多个不连续的时段]

25 8-11 * * * ls //每天8-11点的第25分钟执行ls命令[注:”-”用来连接连续的时段]

*/15 * * * * ls //每15分钟执行一次ls命令 [即每个小时的第0 15 30 45 60分钟执行ls命令 ]

30 6 */10 * * ls //每个月中,每隔10天6:30执行一次ls命令[即每月的1、11、21、31日是的6:30执行一次ls命令。 ]

50 7 * * * root run-parts /etc/cron.daily //每天7:50以root 身份执行/etc/cron.daily目录中的所有可执行文件[ 注:run-parts参数表示,执行后面目录中的所有可执行文件。 ]6.新增调度任务可用两种方法:

a.在命令行输入: crontab -e 然后添加相应的任务,wq存盘退出。

b.直接编辑/etc/crontab 文件,即vi /etc/crontab,添加相应的任务。 查看全部
crond 是linux用来定期执行程序的命令。当安装完成操作系统之后,默认便会启动此任务调度命令。crond命令每分锺会定期检查是否有要执行的工作,如果有要执行的工作便会自动执行该工作。可以用以下的方法启动、关闭这个服务:
/sbin/service crond start //启动服务

/sbin/service crond stop //关闭服务

/sbin/service crond restart //重启服务

/sbin/service crond reload //重新载入配置
1.linux任务调度的工作主要分为以下两类:


系统执行的工作:系统周期性所要执行的工作,如备份系统数据、清理缓存

个人执行的工作:某个用户定期要做的工作,例如每隔10分钟检查邮件服务器是否有新信,这些工作可由每个用户自行设置。



2.crontab命令选项:

cron服务提供crontab命令来设定cron服务的,以下是这个命令的一些参数与说明:

crontab -u //设定某个用户的cron服务,一般root用户在执行这个命令的时候需要此参数

crontab -l //列出某个用户cron服务的详细内容

crontab -r //删除某个用户的cron服务

crontab -e //编辑某个用户的cron服务

比如说root查看自己的cron设置:crontab -u root -l

再例如,root想删除fred的cron设置:crontab -u fred -r

在编辑cron服务时,编辑的内容有一些格式和约定,输入:crontab -u root -e

进入vi编辑模式,编辑的内容一定要符合下面的格式:*/1 * * * * ls >> /tmp/ls.txt

3.cron文件语法
  分     小时      日       月       星期      命令

0-59 0-23 1-31 1-12 0-6 command (取值范围,0表示周日一般一行对应一个任务)
4.记住几个特殊符号的含义:

"*"代表取值范围内的数字,

"/"代表"每",

"-"代表从某个数字到某个数字,

","分开几个离散的数字
 
5.举几个例子
5       *       *       *      *     ls              //指定每小时的第5分钟执行一次ls命令

30 5 * * * ls //指定每天的 5:30 执行ls命令

30 7 8 * * ls //指定每月8号的7:30分执行ls命令

30 5 8 6 * ls //指定每年的6月8日5:30执行ls命令

30 6 * * 0 ls //指定每星期日的6:30执行ls命令[注:0表示星期天,1表示星期1,以此类推,也可以用英文来表示,sun表示星期天,mon表示星期一等。]

30 3 10,20 * * ls //每月10号及20号的3:30执行ls命令[注:”,”用来连接多个不连续的时段]

25 8-11 * * * ls //每天8-11点的第25分钟执行ls命令[注:”-”用来连接连续的时段]

*/15 * * * * ls //每15分钟执行一次ls命令 [即每个小时的第0 15 30 45 60分钟执行ls命令 ]

30 6 */10 * * ls //每个月中,每隔10天6:30执行一次ls命令[即每月的1、11、21、31日是的6:30执行一次ls命令。 ]

50 7 * * * root run-parts /etc/cron.daily //每天7:50以root 身份执行/etc/cron.daily目录中的所有可执行文件[ 注:run-parts参数表示,执行后面目录中的所有可执行文件。 ]
6.新增调度任务可用两种方法:

a.在命令行输入: crontab -e 然后添加相应的任务,wq存盘退出。

b.直接编辑/etc/crontab 文件,即vi /etc/crontab,添加相应的任务。

类设计的六大基本原则

架构思想zkbhj 发表了文章 • 0 个评论 • 80 次浏览 • 2018-11-12 20:12 • 来自相关话题

一.单一职责原则

Single Responsibility Principle, 简称SRP。

定义:There should never be more than one reason for a class to change.

应该有且仅有一个原因引起类的变更。
 
二.里氏替换原则

Liskov Substitution Principle, 简称LSP。

定义:Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

(所有引用基类的地方必须能透明地使用其子类的对象)
 
三.依赖倒置原则

Dependence Inversion Principle, 简称DIP

定义:High level modules should not depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details.Details should depend upon abstractions.

翻译过来,包含三层含义:

1.高层模块不应该依赖低层模块,两者都应该依赖其抽象。2.抽象不应该依赖细节。3.细节应该依赖抽象。

精简的定义: 面向接口编程。
 
四.接口隔离原则:
接口--这里指用interface关键字定义的接口。
定义:
1.Clients should not be forced to depend upon interfaces that they don't use.(客户端不应该依赖它不需要的接口)
2.The dependency of one class to anther one should depend on the smallest possible interface.(类间的依赖关系应该建立在最小的接口上)

概括:建立单一接口,不要建立臃肿庞大的接口。通俗来讲:接口尽量细化,同时接口中的方法尽量少。
 
五.迪米特法则
Law of Demeter, LOD。又称最少知识原则(Least Knowledge Principle, LKP)。
通俗来讲:一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我没有关系,那是你的事情,我就调用你提供的public方法,其他一概不关心。
 
六.开闭原则
Software entities like classes, modules and functions should be open for extension but closed for modifications.(一个软件实体如类、模块和函数应该对扩展开放,对修改关闭) 查看全部
一.单一职责原则

Single Responsibility Principle, 简称SRP。

定义:There should never be more than one reason for a class to change.

应该有且仅有一个原因引起类的变更。
 
二.里氏替换原则

Liskov Substitution Principle, 简称LSP。

定义:Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

(所有引用基类的地方必须能透明地使用其子类的对象)
 
三.依赖倒置原则

Dependence Inversion Principle, 简称DIP

定义:High level modules should not depend upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details.Details should depend upon abstractions.

翻译过来,包含三层含义:

1.高层模块不应该依赖低层模块,两者都应该依赖其抽象。2.抽象不应该依赖细节。3.细节应该依赖抽象。

精简的定义: 面向接口编程。
 
四.接口隔离原则:
接口--这里指用interface关键字定义的接口。
定义:
1.Clients should not be forced to depend upon interfaces that they don't use.(客户端不应该依赖它不需要的接口)
2.The dependency of one class to anther one should depend on the smallest possible interface.(类间的依赖关系应该建立在最小的接口上)

概括:建立单一接口,不要建立臃肿庞大的接口。通俗来讲:接口尽量细化,同时接口中的方法尽量少。
 
五.迪米特法则
Law of Demeter, LOD。又称最少知识原则(Least Knowledge Principle, LKP)。
通俗来讲:一个类应该对自己需要耦合或调用的类知道得最少,你(被耦合或调用的类)的内部是如何复杂都和我没有关系,那是你的事情,我就调用你提供的public方法,其他一概不关心。
 
六.开闭原则
Software entities like classes, modules and functions should be open for extension but closed for modifications.(一个软件实体如类、模块和函数应该对扩展开放,对修改关闭)

政府发布的白皮书是什么?

专业名词zkbhj 发表了文章 • 0 个评论 • 217 次浏览 • 2018-09-25 19:28 • 来自相关话题

最近,我被一个老词汇所困扰,那就是在公司里常常见到的“白皮书”一词。与此对应的,我们还经常听到、看到“蓝皮书”、“红皮书”,还有“桔皮书”,等等,这些书都是什么意思,他们之间有区别吗?
和同事争论的时候,有的说白皮书就是产品介绍文档,有的说不是。那么在技术型公司里,白皮书究竟指的是什么呢?
为此,我到网上查找,中文的网页百度百科说:“白皮书”是政府或议会正式发表的以白色封面装帧的重要文件或报告书的别称。这多少让我有点失望,它并没有谈及商业上的白皮书。
后来又找到了维基百科,里面对白皮书是这样解释的,这多少让我找到了感觉。
一个白皮书(英文White paper或whitepaper)是一个权威性的报告或指南,常常阐述问题本身及其解决方法。白皮书被用来教育读者并帮助人们作出决定。常被用在政治、商业和技术领域。在商业领域,这个术语指的是作为市场或销售工具的商业文档。

政府白皮书

在英联邦国家,白皮书是议会文件的一种非正式名称,用来阐述政府政策;在英国,这些文件常被称为命令文件(Command Papers)。白皮书由政府发行,阐明在现时的问题上的政策,或建议采取的行动。尽管白皮书可能有时作为新法立法前的细节咨询,但是,透过白皮书,确实能看出政府有着清晰的意图:他们欲通过一部新法。
由欧洲委员会发表的白皮书,是欧盟在某一特定领域采取行动的建议文稿。他们有时紧随绿皮书发布其后,开展公众咨询过程。

这里有几个例子:
俄罗斯1号,关于俄罗斯布尔什维主义的报告汇编,1919年4月。这个报告汇编常被称作“白皮书”(The White Paper),是一本关于布尔什维克革命的电报信息的汇编,由英国在俄罗斯的官员撰写。丘吉尔白皮书,1922,计划为犹太人在巴勒斯坦设立一个国家1939年白皮书,呼吁建立统一的巴勒斯坦国,并限制犹太人移民和购买土地的能力。全民就业白皮书,1945。澳大利亚联邦承认让人民工作是国家的义务。国防白皮书,1964,导致创立并统一了现代化的加拿大军队。1966国防白皮书,取消了英国新航母和BAC TSR-2战术打击飞机。In Place of Strife, 1969 (后被弃)减少工会的权利。1969白皮书,1969(后被弃),在加拿大废弃“印第安人法”, 印第安人象加拿大其他少数民族一样被承认是这个国家的原住民,而不是特殊一族。白皮书,1966,美国国家研究理事会文件,导致在美国开发紧急医疗服务。
商业白皮书

自上世纪90年代早期,白皮书一词也用来指商业性的文件,作为市场宣传和销售的工具。这类白皮书阐明:某类技术或产品为解决特定领域问题带来的好处。
这类白皮书几乎总是用作市场沟通,目的是推销公司的解决方案和产品。作为市场宣传的工具,这些文件将突出对公司有利的信息。这样的白皮书常被用来发现销售线索、标榜领先地位、争取业务单子或纯粹是为了教育客户。

有三种主要的商业白皮书:
业务-利益:为某一特定的技术或方法争取业务定单。技术:描述一个技术是如何工作的。上面两者的混合:在一个文件里,将宏观的商业利益和微观的技术细节结合在一起。 查看全部
最近,我被一个老词汇所困扰,那就是在公司里常常见到的“白皮书”一词。与此对应的,我们还经常听到、看到“蓝皮书”、“红皮书”,还有“桔皮书”,等等,这些书都是什么意思,他们之间有区别吗?
和同事争论的时候,有的说白皮书就是产品介绍文档,有的说不是。那么在技术型公司里,白皮书究竟指的是什么呢?
为此,我到网上查找,中文的网页百度百科说:“白皮书”是政府或议会正式发表的以白色封面装帧的重要文件或报告书的别称。这多少让我有点失望,它并没有谈及商业上的白皮书。
后来又找到了维基百科,里面对白皮书是这样解释的,这多少让我找到了感觉。
一个白皮书(英文White paper或whitepaper)是一个权威性的报告或指南,常常阐述问题本身及其解决方法。白皮书被用来教育读者并帮助人们作出决定。常被用在政治、商业和技术领域。在商业领域,这个术语指的是作为市场或销售工具的商业文档。

政府白皮书

在英联邦国家,白皮书是议会文件的一种非正式名称,用来阐述政府政策;在英国,这些文件常被称为命令文件(Command Papers)。白皮书由政府发行,阐明在现时的问题上的政策,或建议采取的行动。尽管白皮书可能有时作为新法立法前的细节咨询,但是,透过白皮书,确实能看出政府有着清晰的意图:他们欲通过一部新法。
由欧洲委员会发表的白皮书,是欧盟在某一特定领域采取行动的建议文稿。他们有时紧随绿皮书发布其后,开展公众咨询过程。

这里有几个例子:
  • 俄罗斯1号,关于俄罗斯布尔什维主义的报告汇编,1919年4月。这个报告汇编常被称作“白皮书”(The White Paper),是一本关于布尔什维克革命的电报信息的汇编,由英国在俄罗斯的官员撰写。
  • 丘吉尔白皮书,1922,计划为犹太人在巴勒斯坦设立一个国家
  • 1939年白皮书,呼吁建立统一的巴勒斯坦国,并限制犹太人移民和购买土地的能力。
  • 全民就业白皮书,1945。澳大利亚联邦承认让人民工作是国家的义务。
  • 国防白皮书,1964,导致创立并统一了现代化的加拿大军队。
  • 1966国防白皮书,取消了英国新航母和BAC TSR-2战术打击飞机。
  • In Place of Strife, 1969 (后被弃)减少工会的权利。
  • 1969白皮书,1969(后被弃),在加拿大废弃“印第安人法”, 印第安人象加拿大其他少数民族一样被承认是这个国家的原住民,而不是特殊一族。
  • 白皮书,1966,美国国家研究理事会文件,导致在美国开发紧急医疗服务。

商业白皮书

自上世纪90年代早期,白皮书一词也用来指商业性的文件,作为市场宣传和销售的工具。这类白皮书阐明:某类技术或产品为解决特定领域问题带来的好处。
这类白皮书几乎总是用作市场沟通,目的是推销公司的解决方案和产品。作为市场宣传的工具,这些文件将突出对公司有利的信息。这样的白皮书常被用来发现销售线索、标榜领先地位、争取业务单子或纯粹是为了教育客户。

有三种主要的商业白皮书:
  • 业务-利益:为某一特定的技术或方法争取业务定单。
  • 技术:描述一个技术是如何工作的。
  • 上面两者的混合:在一个文件里,将宏观的商业利益和微观的技术细节结合在一起。

什么是双因子认证?双因子认证的好处是什么?

专业名词zkbhj 发表了文章 • 1 个评论 • 330 次浏览 • 2018-09-19 15:08 • 来自相关话题

双因子认证(2FA)是指结合密码以及实物(信用卡、SMS手机、令牌或指纹等生物标志)两种条件对用户的身份进行认证的方法。这种方法已经得到了企业的广泛采用,特别是在对数据进行远程访问时,但在其它领域应用还十分有限。双因子身份认证的推广之所以受阻,主要是由于其需要使用额外的工具,而这一条件为IT和技术支持人员带来了不小的负担。其批评者还指出,这种安全保障措施仍然很容易遭受攻击,即在非常小的时间周期内,这种技术很容易受到中间人(man-in-the-middle)攻击(这也是采用严格SSL处理的主要原因)。实际上,除了这些障碍以外,现在我们已经开始认识到,不采用双因子认证所带来的隐含成本远远比采用双因子认证所需要的成本高得多。






双因子身份认证是确保远程访问安全性的最佳实践方式,但是这种技术也给了一些网络犯罪分子可乘之机。如果攻击者在获取到了大量身份凭证的情况下,他们就可以伪装成合法用户,而且还可以躲避安全防护软件的检测。很多公司都认为双因子认证机制是绝对可靠的,而且也没有采取一定的安全预防措施来防御攻击者的攻击以及系统后门。

在这篇文章中,我们将会站在攻击者的角度来对双因子身份验证机制进行从浅至深的分析,我们希望这篇文章能够帮助安全研究人员解决这项技术中目前所存在的一些问题。我将会对远程绕过双因子身份验证技术进行讨论,并且向大家描述如何绕过远程访问设备的双因子身份验证机制,并从内部网络环境的设备中窃取数据。

1)K.I.S.S-简单,有效

入侵设备的远程访问控制是攻击者首要解决的问题,因为它可以给攻击者提供设备的访问权限,并且降低被监测到的可能性。在合法远程访问工具的帮助下,攻击者不仅可以在目标主机中执行控制命令,而且还可以在身份验证机制的掩护下进行其他的一些攻击活动。

在某些较为困难的情况下,我们可以使用一些比较直接的方法来获取到我们所需的凭证:让目标用户代替我们来进行操作。我们只需进行一些简单的设置就可以制作一个完美的陷阱。

在下图中,我们可以看到两个不同的VPN登录页面。其中一个是公司的合法登录网站,另一个是由攻击者伪造的虚假登录页面。你能发现这两者之间的区别吗?





 
分辨不出吗?没错,你的客户也一样分辨不出。在社会工程学工具(SET)的帮助下,任何人都可以快速地复制出一个外部页面来欺骗用户(攻击者只需要将HTML页面中的本地资源地址(“/home/image/logo.png”)修改成外部引用地址(“mycompany.com/home/image/logo.png”)就可以了)。在一次完美的网络钓鱼攻击中,你可以引诱目标用户访问你所克隆出的虚假VPN身份验证页面,并且得到所有你需要的信息:用户名,密码,甚至是令牌码!

如果攻击者的操作速度足够快,那么他们还可以将凭证提交至虚假的VPN页面,然后利用这些信息来登录真实的VPN。如下图所示,攻击者可以将登录提交请求重定向至一个PHP脚本,然后这个脚本就会将提交过来的用户名,密码,以及其他的一些元数据写入服务器的日志文件中,这样攻击者就可以检测并获取到用户所提交的双因子身份验证信息了。




当攻击者通过了VPN的身份验证之后,他们就可以在安全检测软件检测到钓鱼攻击并进行安全响应之前,在目标主机中实现提权并获取到敏感数据。

2)电子邮件就是我们的敌人

数字令牌通常会需要一个同步代码,而为了保证其有效性,每一名用户的令牌都只会有一个唯一的同步码与之对应。同步码和算法是保证令牌安全性的因素,而且这两个因素也可以确保用户令牌能够与身份验证服务器的要求所匹配。当用户的VPN访问请求通过批准之后,很多公司会选择使用一种简单和友好的方式来向用户发送通知类的电子邮件。这些电子邮件中通常会包含有“seed“密钥和安装说明。但对于安全团队来说不幸的是,用户通常在阅读完这类电子邮件之后,却忘记将其删除了,这些电子邮件就这样躺在了用户的收件箱之中,等待着攻击者前来窃取。

攻击者可以在用户的电子邮箱中搜索敏感文件和有价值的信息(包括硬盘中的.PST和.OST文件)。在大多数情况下,攻击者只需要使用一个简单的PowerShell脚本就可以搜索用户邮箱中的敏感文件以及与RSA软令牌相关的.sdtid文件了。

3)双因子身份验证机制中的紧急模式

在很多的双因子身份验证产品中,都提供有一个名为“紧急访问”的代码,这种运行模式实际上是一种身份验证机制,如果用户丢失了令牌,但是又急需对数据进行远程访问,那么这种机制也可以允许用户进行临时性的VPN访问。下图显示的就是紧急访问模式的操作界面截图:




如上图所示,系统提供了一个身份验证的修复机制。对于攻击者而言,攻击者可以利用这种机制来远程访问目标系统。这些紧急访问码是非常不安全的,因为他们的有效日期可以被修改,这样一来,攻击者就可以利用这些紧急访问码来获取到目标系统的永久访问权限了。

总结

对于一名经验丰富的攻击者来说,他们有很多种方法可以对目标进行攻击,并绕过那些所谓的“安全防护措施“。

不幸的是,很多公司太过于相信那些所谓的安全解决方案了,例如双因子身份验证。如果安全技术人员没有采取一些必要的安全保障措施,那么这种安全技术也不能保证公司的安全。如果安全技术人员忽略了这一点,那么攻击者就可以利用如上文所述的一些攻击方法破坏双因子身份验证技术本该带来的安全性。

在此,我还需要感谢Andrew Burkhardt, Evan Peña, 以及Justin Prosco为这篇文章所做出的贡献。
 
文章原文:https://www.fireeye.com/blog/t ... .html 查看全部
双因子认证(2FA)是指结合密码以及实物(信用卡、SMS手机、令牌或指纹等生物标志)两种条件对用户的身份进行认证的方法。这种方法已经得到了企业的广泛采用,特别是在对数据进行远程访问时,但在其它领域应用还十分有限。双因子身份认证的推广之所以受阻,主要是由于其需要使用额外的工具,而这一条件为IT和技术支持人员带来了不小的负担。其批评者还指出,这种安全保障措施仍然很容易遭受攻击,即在非常小的时间周期内,这种技术很容易受到中间人(man-in-the-middle)攻击(这也是采用严格SSL处理的主要原因)。实际上,除了这些障碍以外,现在我们已经开始认识到,不采用双因子认证所带来的隐含成本远远比采用双因子认证所需要的成本高得多。

t01fc4acdc6ee66ec6e.jpg


双因子身份认证是确保远程访问安全性的最佳实践方式,但是这种技术也给了一些网络犯罪分子可乘之机。如果攻击者在获取到了大量身份凭证的情况下,他们就可以伪装成合法用户,而且还可以躲避安全防护软件的检测。很多公司都认为双因子认证机制是绝对可靠的,而且也没有采取一定的安全预防措施来防御攻击者的攻击以及系统后门。

在这篇文章中,我们将会站在攻击者的角度来对双因子身份验证机制进行从浅至深的分析,我们希望这篇文章能够帮助安全研究人员解决这项技术中目前所存在的一些问题。我将会对远程绕过双因子身份验证技术进行讨论,并且向大家描述如何绕过远程访问设备的双因子身份验证机制,并从内部网络环境的设备中窃取数据。

1)K.I.S.S-简单,有效

入侵设备的远程访问控制是攻击者首要解决的问题,因为它可以给攻击者提供设备的访问权限,并且降低被监测到的可能性。在合法远程访问工具的帮助下,攻击者不仅可以在目标主机中执行控制命令,而且还可以在身份验证机制的掩护下进行其他的一些攻击活动。

在某些较为困难的情况下,我们可以使用一些比较直接的方法来获取到我们所需的凭证:让目标用户代替我们来进行操作。我们只需进行一些简单的设置就可以制作一个完美的陷阱。

在下图中,我们可以看到两个不同的VPN登录页面。其中一个是公司的合法登录网站,另一个是由攻击者伪造的虚假登录页面。你能发现这两者之间的区别吗?

t01775f75e07e0a35a7.png

 
分辨不出吗?没错,你的客户也一样分辨不出。在社会工程学工具(SET)的帮助下,任何人都可以快速地复制出一个外部页面来欺骗用户(攻击者只需要将HTML页面中的本地资源地址(“/home/image/logo.png”)修改成外部引用地址(“mycompany.com/home/image/logo.png”)就可以了)。在一次完美的网络钓鱼攻击中,你可以引诱目标用户访问你所克隆出的虚假VPN身份验证页面,并且得到所有你需要的信息:用户名,密码,甚至是令牌码!

如果攻击者的操作速度足够快,那么他们还可以将凭证提交至虚假的VPN页面,然后利用这些信息来登录真实的VPN。如下图所示,攻击者可以将登录提交请求重定向至一个PHP脚本,然后这个脚本就会将提交过来的用户名,密码,以及其他的一些元数据写入服务器的日志文件中,这样攻击者就可以检测并获取到用户所提交的双因子身份验证信息了。
fig2.png

当攻击者通过了VPN的身份验证之后,他们就可以在安全检测软件检测到钓鱼攻击并进行安全响应之前,在目标主机中实现提权并获取到敏感数据。

2)电子邮件就是我们的敌人

数字令牌通常会需要一个同步代码,而为了保证其有效性,每一名用户的令牌都只会有一个唯一的同步码与之对应。同步码和算法是保证令牌安全性的因素,而且这两个因素也可以确保用户令牌能够与身份验证服务器的要求所匹配。当用户的VPN访问请求通过批准之后,很多公司会选择使用一种简单和友好的方式来向用户发送通知类的电子邮件。这些电子邮件中通常会包含有“seed“密钥和安装说明。但对于安全团队来说不幸的是,用户通常在阅读完这类电子邮件之后,却忘记将其删除了,这些电子邮件就这样躺在了用户的收件箱之中,等待着攻击者前来窃取。

攻击者可以在用户的电子邮箱中搜索敏感文件和有价值的信息(包括硬盘中的.PST和.OST文件)。在大多数情况下,攻击者只需要使用一个简单的PowerShell脚本就可以搜索用户邮箱中的敏感文件以及与RSA软令牌相关的.sdtid文件了。

3)双因子身份验证机制中的紧急模式

在很多的双因子身份验证产品中,都提供有一个名为“紧急访问”的代码,这种运行模式实际上是一种身份验证机制,如果用户丢失了令牌,但是又急需对数据进行远程访问,那么这种机制也可以允许用户进行临时性的VPN访问。下图显示的就是紧急访问模式的操作界面截图:
fig9.png

如上图所示,系统提供了一个身份验证的修复机制。对于攻击者而言,攻击者可以利用这种机制来远程访问目标系统。这些紧急访问码是非常不安全的,因为他们的有效日期可以被修改,这样一来,攻击者就可以利用这些紧急访问码来获取到目标系统的永久访问权限了。

总结

对于一名经验丰富的攻击者来说,他们有很多种方法可以对目标进行攻击,并绕过那些所谓的“安全防护措施“。

不幸的是,很多公司太过于相信那些所谓的安全解决方案了,例如双因子身份验证。如果安全技术人员没有采取一些必要的安全保障措施,那么这种安全技术也不能保证公司的安全。如果安全技术人员忽略了这一点,那么攻击者就可以利用如上文所述的一些攻击方法破坏双因子身份验证技术本该带来的安全性。

在此,我还需要感谢Andrew Burkhardt, Evan Peña, 以及Justin Prosco为这篇文章所做出的贡献。
 
文章原文:https://www.fireeye.com/blog/t ... .html

JWT:完全前后端分离的项目如何做用户身份验证更安全?看这篇就够了!

前端开发zkbhj 发表了文章 • 0 个评论 • 326 次浏览 • 2018-09-19 14:48 • 来自相关话题

在前后端分离开发时为什么需要用户认证呢?原因是由于HTTP协定是不储存状态的(stateless),这意味着当我们透过帐号密码验证一个使用者时,当下一个request请求时它就把刚刚的资料忘了。于是我们的程序就不知道谁是谁,就要再验证一次。所以为了保证系统安全,我们就需要验证用户否处于登录状态。

传统方式

前后端分离通过Restful API进行数据交互时,如何验证用户的登录信息及权限。在原来的项目中,使用的是最传统也是最简单的方式,前端登录,后端根据用户信息生成一个token,并保存这个 token 和对应的用户id到数据库或Session中,接着把 token 传给用户,存入浏览器 cookie,之后浏览器请求带上这个cookie,后端根据这个cookie值来查询用户,验证是否过期。

但这样做问题就很多,如果我们的页面出现了 XSS 漏洞,由于 cookie 可以被 JavaScript 读取,XSS 漏洞会导致用户 token 泄露,而作为后端识别用户的标识,cookie 的泄露意味着用户信息不再安全。尽管我们通过转义输出内容,使用 CDN 等可以尽量避免 XSS 注入,但谁也不能保证在大型的项目中不会出现这个问题。

在设置 cookie 的时候,其实你还可以设置 httpOnly 以及 secure 项。设置 httpOnly 后 cookie 将不能被 JS 读取,浏览器会自动的把它加在请求的 header 当中,设置 secure 的话,cookie 就只允许通过 HTTPS 传输。secure 选项可以过滤掉一些使用 HTTP 协议的 XSS 注入,但并不能完全阻止。

httpOnly 选项使得 JS 不能读取到 cookie,那么 XSS 注入的问题也基本不用担心了。但设置 httpOnly 就带来了另一个问题,就是很容易的被 XSRF,即跨站请求伪造。当你浏览器开着这个页面的时候,另一个页面可以很容易的跨站请求这个页面的内容。因为 cookie 默认被发了出去。

另外,如果将验证信息保存在数据库中,后端每次都需要根据token查出用户id,这就增加了数据库的查询和存储开销。若把验证信息保存在session中,有加大了服务器端的存储压力。那我们可不可以不要服务器去查询呢?如果我们生成token遵循一定的规律,比如我们使用对称加密算法来加密用户id形成token,那么服务端以后其实只要解密该token就可以知道用户的id是什么了。不过呢,我只是举个例子而已,要是真这么做,只要你的对称加密算法泄露了,其他人可以通过这种加密方式进行伪造token,那么所有用户信息都不再安全了。恩,那用非对称加密算法来做呢,其实现在有个规范就是这样做的,就是我们接下来要介绍的 JWT。

Json Web Token(JWT)

JWT 是一个开放标准(RFC 7519),它定义了一种用于简洁,自包含的用于通信双方之间以 JSON 对象的形式安全传递信息的方法。JWT 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名。它具备两个特点:

简洁(Compact)

可以通过URL, POST 参数或者在 HTTP header 发送,因为数据量小,传输速度快

自包含(Self-contained)

负载中包含了所有用户所需要的信息,避免了多次查询数据库


JWT 组成





Header 头部

头部包含了两部分,token 类型和采用的加密算法
 {
"alg": "HS256",
"typ": "JWT"
}它会使用 Base64 编码组成 JWT 结构的第一部分,如果你使用Node.js,可以用Node.js的包base64url来得到这个字符串。

Base64是一种编码,也就是说,它是可以被翻译回原来的样子来的。它并不是一种加密过程。

Payload 负载

这部分就是我们存放信息的地方了,你可以把用户 ID 等信息放在这里,JWT 规范里面对这部分有进行了比较详细的介绍,常用的由 iss(签发者),exp(过期时间),sub(面向的用户),aud(接收方),iat(签发时间)。
 {
"iss": "lion1ou JWT",
"iat": 1441593502,
"exp": 1441594722,
"aud": "www.example.com",
"sub": "lion1ou@163.com"
}同样的,它会使用 Base64 编码组成 JWT 结构的第二部分

Signature 签名

前面两部分都是使用 Base64 进行编码的,即前端可以解开知道里面的信息。Signature 需要使用编码后的 header 和 payload 以及我们提供的一个密钥,然后使用 header 中指定的签名算法(HS256)进行签名。签名的作用是保证 JWT 没有被篡改过。

三个部分通过.连接在一起就是我们的 JWT 了,它可能长这个样子,长度貌似和你的加密算法和私钥有关系。eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjU3ZmVmMTY0ZTU0YWY2NGZmYzUzZGJkNSIsInhzcmYiOiI0ZWE1YzUwOGE2NTY2ZTc2MjQwNTQzZjhmZWIwNmZkNDU3Nzc3YmUzOTU0OWM0MDE2NDM2YWZkYTY1ZDIzMzBlIiwiaWF0IjoxNDc2NDI3OTMzfQ.PA3QjeyZSUh7H0GfE0vJaKW4LjKJuC3dVLQiY4hii8s

其实到这一步可能就有人会想了,HTTP 请求总会带上 token,这样这个 token 传来传去占用不必要的带宽啊。如果你这么想了,那你可以去了解下 HTTP2,HTTP2 对头部进行了压缩,相信也解决了这个问题。

签名的目的

最后一步签名的过程,实际上是对头部以及负载内容进行签名,防止内容被窜改。如果有人对头部以及负载的内容解码之后进行修改,再进行编码,最后加上之前的签名组合形成新的JWT的话,那么服务器端会判断出新的头部和负载形成的签名和JWT附带上的签名是不一样的。如果要对新的头部和负载进行签名,在不知道服务器加密时用的密钥的话,得出来的签名也是不一样的。

信息暴露

在这里大家一定会问一个问题:Base64是一种编码,是可逆的,那么我的信息不就被暴露了吗?

是的。所以,在JWT中,不应该在负载里面加入任何敏感的数据。在上面的例子中,我们传输的是用户的User ID。这个值实际上不是什么敏感内容,一般情况下被知道也是安全的。但是像密码这样的内容就不能被放在JWT中了。如果将用户的密码放在了JWT中,那么怀有恶意的第三方通过Base64解码就能很快地知道你的密码了。

因此JWT适合用于向Web应用传递一些非敏感信息。JWT还经常用于设计用户认证和授权系统,甚至实现Web应用的单点登录。

JWT 使用




 
首先,前端通过Web表单将自己的用户名和密码发送到后端的接口。这一过程一般是一个HTTP POST请求。建议的方式是通过SSL加密的传输(https协议),从而避免敏感信息被嗅探。后端核对用户名和密码成功后,将用户的id等其他信息作为JWT Payload(负载),将其与头部分别进行Base64编码拼接后签名,形成一个JWT。形成的JWT就是一个形同lll.zzz.xxx的字符串。后端将JWT字符串作为登录成功的返回结果返回给前端。前端可以将返回的结果保存在localStorage或sessionStorage上,退出登录时前端删除保存的JWT即可。前端在每次请求时将JWT放入HTTP Header中的Authorization位。(解决XSS和XSRF问题)后端检查是否存在,如存在验证JWT的有效性。例如,检查签名是否正确;检查Token是否过期;检查Token的接收方是否是自己(可选)。验证通过后后端使用JWT中包含的用户信息进行其他逻辑操作,返回相应结果。

和Session方式存储id的差异

Session方式存储用户id的最大弊病在于Session是存储在服务器端的,所以需要占用大量服务器内存,对于较大型应用而言可能还要保存许多的状态。一般而言,大型应用还需要借助一些KV数据库和一系列缓存机制来实现Session的存储。

而JWT方式将用户状态分散到了客户端中,可以明显减轻服务端的内存压力。除了用户id之外,还可以存储其他的和用户相关的信息,例如该用户是否是管理员、用户所在的分组等。虽说JWT方式让服务器有一些计算压力(例如加密、编码和解码),但是这些压力相比磁盘存储而言可能就不算什么了。具体是否采用,需要在不同场景下用数据说话。

单点登录

Session方式来存储用户id,一开始用户的Session只会存储在一台服务器上。对于有多个子域名的站点,每个子域名至少会对应一台不同的服务器,例如:www.taobao.com,nv.taobao.com,nz.taobao.com,login.taobao.com。所以如果要实现在login.taobao.com登录后,在其他的子域名下依然可以取到Session,这要求我们在多台服务器上同步Session。使用JWT的方式则没有这个问题的存在,因为用户的状态已经被传送到了客户端。

总结

JWT的主要作用在于(一)可附带用户信息,后端直接通过JWT获取相关信息。(二)使用本地保存,通过HTTP Header中的Authorization位提交验证。但其实关于JWT存放到哪里一直有很多讨论,有人说存放到本地存储,有人说存 cookie。个人偏向于放在本地存储,如果你有什么意见和看法欢迎提出。

参考文档:
https://segmentfault.com/a/1190000005783306 
https://ruiming.me/authentication-of-frontend-backend-separate-application/ 
 
总结和摘录自:
https://blog.csdn.net/kevin_lc ... 46723 查看全部
在前后端分离开发时为什么需要用户认证呢?原因是由于HTTP协定是不储存状态的(stateless),这意味着当我们透过帐号密码验证一个使用者时,当下一个request请求时它就把刚刚的资料忘了。于是我们的程序就不知道谁是谁,就要再验证一次。所以为了保证系统安全,我们就需要验证用户否处于登录状态。

传统方式

前后端分离通过Restful API进行数据交互时,如何验证用户的登录信息及权限。在原来的项目中,使用的是最传统也是最简单的方式,前端登录,后端根据用户信息生成一个token,并保存这个 token 和对应的用户id到数据库或Session中,接着把 token 传给用户,存入浏览器 cookie,之后浏览器请求带上这个cookie,后端根据这个cookie值来查询用户,验证是否过期。

但这样做问题就很多,如果我们的页面出现了 XSS 漏洞,由于 cookie 可以被 JavaScript 读取,XSS 漏洞会导致用户 token 泄露,而作为后端识别用户的标识,cookie 的泄露意味着用户信息不再安全。尽管我们通过转义输出内容,使用 CDN 等可以尽量避免 XSS 注入,但谁也不能保证在大型的项目中不会出现这个问题。

在设置 cookie 的时候,其实你还可以设置 httpOnly 以及 secure 项。设置 httpOnly 后 cookie 将不能被 JS 读取,浏览器会自动的把它加在请求的 header 当中,设置 secure 的话,cookie 就只允许通过 HTTPS 传输。secure 选项可以过滤掉一些使用 HTTP 协议的 XSS 注入,但并不能完全阻止。

httpOnly 选项使得 JS 不能读取到 cookie,那么 XSS 注入的问题也基本不用担心了。但设置 httpOnly 就带来了另一个问题,就是很容易的被 XSRF,即跨站请求伪造。当你浏览器开着这个页面的时候,另一个页面可以很容易的跨站请求这个页面的内容。因为 cookie 默认被发了出去。

另外,如果将验证信息保存在数据库中,后端每次都需要根据token查出用户id,这就增加了数据库的查询和存储开销。若把验证信息保存在session中,有加大了服务器端的存储压力。那我们可不可以不要服务器去查询呢?如果我们生成token遵循一定的规律,比如我们使用对称加密算法来加密用户id形成token,那么服务端以后其实只要解密该token就可以知道用户的id是什么了。不过呢,我只是举个例子而已,要是真这么做,只要你的对称加密算法泄露了,其他人可以通过这种加密方式进行伪造token,那么所有用户信息都不再安全了。恩,那用非对称加密算法来做呢,其实现在有个规范就是这样做的,就是我们接下来要介绍的 JWT。

Json Web Token(JWT)

JWT 是一个开放标准(RFC 7519),它定义了一种用于简洁,自包含的用于通信双方之间以 JSON 对象的形式安全传递信息的方法。JWT 可以使用 HMAC 算法或者是 RSA 的公钥密钥对进行签名。它具备两个特点:


简洁(Compact)

可以通过URL, POST 参数或者在 HTTP header 发送,因为数据量小,传输速度快

自包含(Self-contained)

负载中包含了所有用户所需要的信息,避免了多次查询数据库



JWT 组成

006tNc79gy1fbv54tfilmj31120b2wl9.jpg

Header 头部

头部包含了两部分,token 类型和采用的加密算法
 
{
"alg": "HS256",
"typ": "JWT"
}
它会使用 Base64 编码组成 JWT 结构的第一部分,如果你使用Node.js,可以用Node.js的包base64url来得到这个字符串。


Base64是一种编码,也就是说,它是可以被翻译回原来的样子来的。它并不是一种加密过程。


Payload 负载

这部分就是我们存放信息的地方了,你可以把用户 ID 等信息放在这里,JWT 规范里面对这部分有进行了比较详细的介绍,常用的由 iss(签发者),exp(过期时间),sub(面向的用户),aud(接收方),iat(签发时间)。
 
{
"iss": "lion1ou JWT",
"iat": 1441593502,
"exp": 1441594722,
"aud": "www.example.com",
"sub": "lion1ou@163.com"
}
同样的,它会使用 Base64 编码组成 JWT 结构的第二部分

Signature 签名

前面两部分都是使用 Base64 进行编码的,即前端可以解开知道里面的信息。Signature 需要使用编码后的 header 和 payload 以及我们提供的一个密钥,然后使用 header 中指定的签名算法(HS256)进行签名。签名的作用是保证 JWT 没有被篡改过。

三个部分通过.连接在一起就是我们的 JWT 了,它可能长这个样子,长度貌似和你的加密算法和私钥有关系。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjU3ZmVmMTY0ZTU0YWY2NGZmYzUzZGJkNSIsInhzcmYiOiI0ZWE1YzUwOGE2NTY2ZTc2MjQwNTQzZjhmZWIwNmZkNDU3Nzc3YmUzOTU0OWM0MDE2NDM2YWZkYTY1ZDIzMzBlIiwiaWF0IjoxNDc2NDI3OTMzfQ.PA3QjeyZSUh7H0GfE0vJaKW4LjKJuC3dVLQiY4hii8s

其实到这一步可能就有人会想了,HTTP 请求总会带上 token,这样这个 token 传来传去占用不必要的带宽啊。如果你这么想了,那你可以去了解下 HTTP2,HTTP2 对头部进行了压缩,相信也解决了这个问题。

签名的目的

最后一步签名的过程,实际上是对头部以及负载内容进行签名,防止内容被窜改。如果有人对头部以及负载的内容解码之后进行修改,再进行编码,最后加上之前的签名组合形成新的JWT的话,那么服务器端会判断出新的头部和负载形成的签名和JWT附带上的签名是不一样的。如果要对新的头部和负载进行签名,在不知道服务器加密时用的密钥的话,得出来的签名也是不一样的。

信息暴露

在这里大家一定会问一个问题:Base64是一种编码,是可逆的,那么我的信息不就被暴露了吗?

是的。所以,在JWT中,不应该在负载里面加入任何敏感的数据。在上面的例子中,我们传输的是用户的User ID。这个值实际上不是什么敏感内容,一般情况下被知道也是安全的。但是像密码这样的内容就不能被放在JWT中了。如果将用户的密码放在了JWT中,那么怀有恶意的第三方通过Base64解码就能很快地知道你的密码了。

因此JWT适合用于向Web应用传递一些非敏感信息。JWT还经常用于设计用户认证和授权系统,甚至实现Web应用的单点登录。

JWT 使用

006tNc79gy1fbv63pzqocj30pj0h8t9m.jpg
 
  1. 首先,前端通过Web表单将自己的用户名和密码发送到后端的接口。这一过程一般是一个HTTP POST请求。建议的方式是通过SSL加密的传输(https协议),从而避免敏感信息被嗅探。
  2. 后端核对用户名和密码成功后,将用户的id等其他信息作为JWT Payload(负载),将其与头部分别进行Base64编码拼接后签名,形成一个JWT。形成的JWT就是一个形同lll.zzz.xxx的字符串。
  3. 后端将JWT字符串作为登录成功的返回结果返回给前端。前端可以将返回的结果保存在localStorage或sessionStorage上,退出登录时前端删除保存的JWT即可。
  4. 前端在每次请求时将JWT放入HTTP Header中的Authorization位。(解决XSS和XSRF问题)
  5. 后端检查是否存在,如存在验证JWT的有效性。例如,检查签名是否正确;检查Token是否过期;检查Token的接收方是否是自己(可选)。
  6. 验证通过后后端使用JWT中包含的用户信息进行其他逻辑操作,返回相应结果。


和Session方式存储id的差异

Session方式存储用户id的最大弊病在于Session是存储在服务器端的,所以需要占用大量服务器内存,对于较大型应用而言可能还要保存许多的状态。一般而言,大型应用还需要借助一些KV数据库和一系列缓存机制来实现Session的存储。

而JWT方式将用户状态分散到了客户端中,可以明显减轻服务端的内存压力。除了用户id之外,还可以存储其他的和用户相关的信息,例如该用户是否是管理员、用户所在的分组等。虽说JWT方式让服务器有一些计算压力(例如加密、编码和解码),但是这些压力相比磁盘存储而言可能就不算什么了。具体是否采用,需要在不同场景下用数据说话。

单点登录

Session方式来存储用户id,一开始用户的Session只会存储在一台服务器上。对于有多个子域名的站点,每个子域名至少会对应一台不同的服务器,例如:www.taobao.com,nv.taobao.com,nz.taobao.com,login.taobao.com。所以如果要实现在login.taobao.com登录后,在其他的子域名下依然可以取到Session,这要求我们在多台服务器上同步Session。使用JWT的方式则没有这个问题的存在,因为用户的状态已经被传送到了客户端。

总结

JWT的主要作用在于(一)可附带用户信息,后端直接通过JWT获取相关信息。(二)使用本地保存,通过HTTP Header中的Authorization位提交验证。但其实关于JWT存放到哪里一直有很多讨论,有人说存放到本地存储,有人说存 cookie。个人偏向于放在本地存储,如果你有什么意见和看法欢迎提出。

参考文档:
https://segmentfault.com/a/1190000005783306 
https://ruiming.me/authentication-of-frontend-backend-separate-application/ 
 
总结和摘录自:
https://blog.csdn.net/kevin_lc ... 46723

海量数据相似度计算算法:simhash和海明距离

架构思想zkbhj 发表了文章 • 0 个评论 • 106 次浏览 • 2018-09-12 16:04 • 来自相关话题

通过 采集系统 我们采集了大量文本数据,但是文本中有很多重复数据影响我们对于结果的分析。分析前我们需要对这些数据去除重复,如何选择和设计文本的去重算法?常见的有余弦夹角算法、欧式距离、Jaccard相似度、最长公共子串、编辑距离等。这些算法对于待比较的文本数据不多时还比较好用,如果我们的爬虫每天采集的数据以千万计算,我们如何对于这些海量千万级的数据进行高效的合并去重。最简单的做法是拿着待比较的文本和数据库中所有的文本比较一遍如果是重复的数据就标示为重复。看起来很简单,我们来做个测试,就拿最简单的两个数据使用Apache提供的 Levenshtein for 循环100w次计算这两个数据的相似度。代码结果如下:
String s1 = "你妈妈喊你回家吃饭哦,回家罗回家罗" ;
String s2 = "你妈妈叫你回家吃饭啦,回家罗回家罗" ;

long t1 = System.currentTimeMillis();

for (int i = 0; i < 1000000; i++) {
int dis = StringUtils .getLevenshteinDistance(s1, s2);
}

long t2 = System.currentTimeMillis();

System. out .println(" 耗费时间: " + (t2 - t1) + " ms ");耗费时间: 4266 ms

大跌眼镜,居然计算耗费4秒。假设我们一天需要比较100w次,光是比较100w次的数据是否重复就需要4s,就算4s一个文档,单线程一分钟才处理15个文档,一个小时才900个,一天也才21600个文档,这个数字和一天100w相差甚远,需要多少机器和资源才能解决。

为此我们需要一种应对于海量数据场景的去重方案,经过研究发现有种叫 local sensitive hash 局部敏感哈希 的东西,据说这玩意可以把文档降维到hash数字,数字两两计算运算量要小很多。查找很多文档后看到google对于网页去重使用的是simhash,他们每天需要处理的文档在亿级别,大大超过了我们现在文档的水平。既然老大哥也有类似的应用,我们也赶紧尝试下。simhash是由 Charikar 在2002年提出来的,参考 《Similarity estimation techniques from rounding algorithms》 。 介绍下这个算法主要原理,为了便于理解尽量不使用数学公式,分为这几步:
 

1、分词,把需要判断文本分词形成这个文章的特征单词。最后形成去掉噪音词的单词序列并为每个词加上权重,我们假设权重分为5个级别(1~5)。比如:“ 美国“51区”雇员称内部有9架飞碟,曾看见灰色外星人 ” ==> 分词后为 “ 美国(4) 51区(5) 雇员(3) 称(1) 内部(2) 有(1) 9架(3) 飞碟(5) 曾(1) 看见(3) 灰色(4) 外星人(5)”,括号里是代表单词在整个句子里重要程度,数字越大越重要。

2、hash,通过hash算法把每个词变成hash值,比如“美国”通过hash算法计算为 100101,“51区”通过hash算法计算为 101011。这样我们的字符串就变成了一串串数字,还记得文章开头说过的吗,要把文章变为数字计算才能提高相似度计算性能,现在是降维过程进行时。

3、加权,通过 2步骤的hash生成结果,需要按照单词的权重形成加权数字串,比如“美国”的hash值为“100101”,通过加权计算为“4 -4 -4 4 -4 4”;“51区”的hash值为“101011”,通过加权计算为 “ 5 -5 5 -5 5 5”。

4、合并,把上面各个单词算出来的序列值累加,变成只有一个序列串。比如 “美国”的 “4 -4 -4 4 -4 4”,“51区”的 “ 5 -5 5 -5 5 5”, 把每一位进行累加, “4+5 -4+-5 -4+5 4+-5 -4+5 4+5” ==》 “9 -9 1 -1 1 9”。这里作为示例只算了两个单词的,真实计算需要把所有单词的序列串累加。

5、降维,把4步算出来的 “9 -9 1 -1 1 9” 变成 0 1 串,形成我们最终的simhash签名。 如果每一位大于0 记为 1,小于0 记为 0。最后算出结果为:“1 0 1 0 1 1”。

 
整个过程图为:





 
大家可能会有疑问,经过这么多步骤搞这么麻烦,不就是为了得到个 0 1 字符串吗?我直接把这个文本作为字符串输入,用hash函数生成 0 1 值更简单。其实不是这样的,传统hash函数解决的是生成唯一值,比如 md5、hashmap等。md5是用于生成唯一签名串,只要稍微多加一个字符md5的两个数字看起来相差甚远;hashmap也是用于键值对查找,便于快速插入和查找的数据结构。不过我们主要解决的是文本相似度计算,要比较的是两个文章是否相识,当然我们降维生成了hashcode也是用于这个目的。看到这里估计大家就明白了,我们使用的simhash就算把文章中的字符串变成 01 串也还是可以用于计算相似度的,而传统的hashcode却不行。我们可以来做个测试,两个相差只有一个字符的文本串,“你妈妈喊你回家吃饭哦,回家罗回家罗” 和 “你妈妈叫你回家吃饭啦,回家罗回家罗”。

通过simhash计算结果为:

1000010010101101111111100000101011010001001111100001001011001011

1000010010101101011111100000101011010001001111100001101010001011

通过 hashcode计算为:

1111111111111111111111111111111110001000001100110100111011011110

1010010001111111110010110011101

大家可以看得出来,相似的文本只有部分 01 串变化了,而普通的hashcode却不能做到,这个就是局部敏感哈希的魅力。目前Broder提出的shingling算法和Charikar的simhash算法应该算是业界公认比较好的算法。在simhash的发明人Charikar的论文中并没有给出具体的simhash算法和证明,“量子图灵”得出的证明simhash是由随机超平面hash算法演变而来的。

现在通过这样的转换,我们把库里的文本都转换为simhash 代码,并转换为long类型存储,空间大大减少。现在我们虽然解决了空间,但是如何计算两个simhash的相似度呢?难道是比较两个simhash的01有多少个不同吗?对的,其实也就是这样,我们通过海明距离(Hamming distance)就可以计算出两个simhash到底相似不相似。两个simhash对应二进制(01串)取值不同的数量称为这两个simhash的海明距离。举例如下: 10101 和 00110 从第一位开始依次有第一位、第四、第五位不同,则海明距离为3。对于二进制字符串的a和b,海明距离为等于在a XOR b运算结果中1的个数(普遍算法)。

为了高效比较,我们预先加载了库里存在文本并转换为simhash code 存储在内存空间。来一条文本先转换为 simhash code,然后和内存里的simhash code 进行比较,测试100w次计算在100ms。速度大大提升。

未完待续:

1、目前速度提升了但是数据是不断增量的,如果未来数据发展到一个小时100w,按现在一次100ms,一个线程处理一秒钟 10次,一分钟 60 * 10 次,一个小时 60*10 *60 次 = 36000次,一天 60*10*60*24 = 864000次。 我们目标是一天100w次,通过增加两个线程就可以完成。但是如果要一个小时100w次呢?则需要增加30个线程和相应的硬件资源保证速度能够达到,这样成本也上去了。能否有更好的办法,提高我们比较的效率?

2、通过大量测试,simhash用于比较大文本,比如500字以上效果都还蛮好,距离小于3的基本都是相似,误判率也比较低。但是如果我们处理的是微博信息,最多也就140个字,使用simhash的效果并不那么理想。看如下图,在距离为3时是一个比较折中的点,在距离为10时效果已经很差了,不过我们测试短文本很多看起来相似的距离确实为10。如果使用距离为3,短文本大量重复信息不会被过滤,如果使用距离为10,长文本的错误率也非常高,如何解决?




  查看全部
通过 采集系统 我们采集了大量文本数据,但是文本中有很多重复数据影响我们对于结果的分析。分析前我们需要对这些数据去除重复,如何选择和设计文本的去重算法?常见的有余弦夹角算法、欧式距离、Jaccard相似度、最长公共子串、编辑距离等。这些算法对于待比较的文本数据不多时还比较好用,如果我们的爬虫每天采集的数据以千万计算,我们如何对于这些海量千万级的数据进行高效的合并去重。最简单的做法是拿着待比较的文本和数据库中所有的文本比较一遍如果是重复的数据就标示为重复。看起来很简单,我们来做个测试,就拿最简单的两个数据使用Apache提供的 Levenshtein for 循环100w次计算这两个数据的相似度。代码结果如下:
String s1 = "你妈妈喊你回家吃饭哦,回家罗回家罗" ;
String s2 = "你妈妈叫你回家吃饭啦,回家罗回家罗" ;

long t1 = System.currentTimeMillis();

for (int i = 0; i < 1000000; i++) {
int dis = StringUtils .getLevenshteinDistance(s1, s2);
}

long t2 = System.currentTimeMillis();

System. out .println(" 耗费时间: " + (t2 - t1) + " ms ");
耗费时间: 4266 ms

大跌眼镜,居然计算耗费4秒。假设我们一天需要比较100w次,光是比较100w次的数据是否重复就需要4s,就算4s一个文档,单线程一分钟才处理15个文档,一个小时才900个,一天也才21600个文档,这个数字和一天100w相差甚远,需要多少机器和资源才能解决。

为此我们需要一种应对于海量数据场景的去重方案,经过研究发现有种叫 local sensitive hash 局部敏感哈希 的东西,据说这玩意可以把文档降维到hash数字,数字两两计算运算量要小很多。查找很多文档后看到google对于网页去重使用的是simhash,他们每天需要处理的文档在亿级别,大大超过了我们现在文档的水平。既然老大哥也有类似的应用,我们也赶紧尝试下。simhash是由 Charikar 在2002年提出来的,参考 《Similarity estimation techniques from rounding algorithms》 。 介绍下这个算法主要原理,为了便于理解尽量不使用数学公式,分为这几步:
 


1、分词,把需要判断文本分词形成这个文章的特征单词。最后形成去掉噪音词的单词序列并为每个词加上权重,我们假设权重分为5个级别(1~5)。比如:“ 美国“51区”雇员称内部有9架飞碟,曾看见灰色外星人 ” ==> 分词后为 “ 美国(4) 51区(5) 雇员(3) 称(1) 内部(2) 有(1) 9架(3) 飞碟(5) 曾(1) 看见(3) 灰色(4) 外星人(5)”,括号里是代表单词在整个句子里重要程度,数字越大越重要。

2、hash,通过hash算法把每个词变成hash值,比如“美国”通过hash算法计算为 100101,“51区”通过hash算法计算为 101011。这样我们的字符串就变成了一串串数字,还记得文章开头说过的吗,要把文章变为数字计算才能提高相似度计算性能,现在是降维过程进行时。

3、加权,通过 2步骤的hash生成结果,需要按照单词的权重形成加权数字串,比如“美国”的hash值为“100101”,通过加权计算为“4 -4 -4 4 -4 4”;“51区”的hash值为“101011”,通过加权计算为 “ 5 -5 5 -5 5 5”。

4、合并,把上面各个单词算出来的序列值累加,变成只有一个序列串。比如 “美国”的 “4 -4 -4 4 -4 4”,“51区”的 “ 5 -5 5 -5 5 5”, 把每一位进行累加, “4+5 -4+-5 -4+5 4+-5 -4+5 4+5” ==》 “9 -9 1 -1 1 9”。这里作为示例只算了两个单词的,真实计算需要把所有单词的序列串累加。

5、降维,把4步算出来的 “9 -9 1 -1 1 9” 变成 0 1 串,形成我们最终的simhash签名。 如果每一位大于0 记为 1,小于0 记为 0。最后算出结果为:“1 0 1 0 1 1”。


 
整个过程图为:

simhash.png

 
大家可能会有疑问,经过这么多步骤搞这么麻烦,不就是为了得到个 0 1 字符串吗?我直接把这个文本作为字符串输入,用hash函数生成 0 1 值更简单。其实不是这样的,传统hash函数解决的是生成唯一值,比如 md5、hashmap等。md5是用于生成唯一签名串,只要稍微多加一个字符md5的两个数字看起来相差甚远;hashmap也是用于键值对查找,便于快速插入和查找的数据结构。不过我们主要解决的是文本相似度计算,要比较的是两个文章是否相识,当然我们降维生成了hashcode也是用于这个目的。看到这里估计大家就明白了,我们使用的simhash就算把文章中的字符串变成 01 串也还是可以用于计算相似度的,而传统的hashcode却不行。我们可以来做个测试,两个相差只有一个字符的文本串,“你妈妈喊你回家吃饭哦,回家罗回家罗” 和 “你妈妈叫你回家吃饭啦,回家罗回家罗”。

通过simhash计算结果为:

1000010010101101111111100000101011010001001111100001001011001011

1000010010101101011111100000101011010001001111100001101010001011

通过 hashcode计算为:

1111111111111111111111111111111110001000001100110100111011011110

1010010001111111110010110011101

大家可以看得出来,相似的文本只有部分 01 串变化了,而普通的hashcode却不能做到,这个就是局部敏感哈希的魅力。目前Broder提出的shingling算法和Charikar的simhash算法应该算是业界公认比较好的算法。在simhash的发明人Charikar的论文中并没有给出具体的simhash算法和证明,“量子图灵”得出的证明simhash是由随机超平面hash算法演变而来的。

现在通过这样的转换,我们把库里的文本都转换为simhash 代码,并转换为long类型存储,空间大大减少。现在我们虽然解决了空间,但是如何计算两个simhash的相似度呢?难道是比较两个simhash的01有多少个不同吗?对的,其实也就是这样,我们通过海明距离(Hamming distance)就可以计算出两个simhash到底相似不相似。两个simhash对应二进制(01串)取值不同的数量称为这两个simhash的海明距离。举例如下: 10101 和 00110 从第一位开始依次有第一位、第四、第五位不同,则海明距离为3。对于二进制字符串的a和b,海明距离为等于在a XOR b运算结果中1的个数(普遍算法)。

为了高效比较,我们预先加载了库里存在文本并转换为simhash code 存储在内存空间。来一条文本先转换为 simhash code,然后和内存里的simhash code 进行比较,测试100w次计算在100ms。速度大大提升。

未完待续:

1、目前速度提升了但是数据是不断增量的,如果未来数据发展到一个小时100w,按现在一次100ms,一个线程处理一秒钟 10次,一分钟 60 * 10 次,一个小时 60*10 *60 次 = 36000次,一天 60*10*60*24 = 864000次。 我们目标是一天100w次,通过增加两个线程就可以完成。但是如果要一个小时100w次呢?则需要增加30个线程和相应的硬件资源保证速度能够达到,这样成本也上去了。能否有更好的办法,提高我们比较的效率?

2、通过大量测试,simhash用于比较大文本,比如500字以上效果都还蛮好,距离小于3的基本都是相似,误判率也比较低。但是如果我们处理的是微博信息,最多也就140个字,使用simhash的效果并不那么理想。看如下图,在距离为3时是一个比较折中的点,在距离为10时效果已经很差了,不过我们测试短文本很多看起来相似的距离确实为10。如果使用距离为3,短文本大量重复信息不会被过滤,如果使用距离为10,长文本的错误率也非常高,如何解决?
simhash2.png

 

PHP函数的参数里,前面三个点的形式...$args是什么含义和用法?

PHPzkbhj 发表了文章 • 0 个评论 • 528 次浏览 • 2018-09-07 13:30 • 来自相关话题

这是PHP5.6添加的功能(一种语法糖): 
可以通过...将函数参数存储在紧接的可遍历的变量中。
 
function add($a, $b, $c)
{
return $a + $b + $c;
}

$num=[2, 3];
echo add(1, ...$num); //6 
上面的第二个和第三个参数将会从$num中循环赋值($b为2,$c为3)。
 
手册地址:http://php.net/manual/zh/migra ... s.php 查看全部
这是PHP5.6添加的功能(一种语法糖): 
可以通过...将函数参数存储在紧接的可遍历的变量中。
 
function add($a, $b, $c)
{
return $a + $b + $c;
}

$num=[2, 3];
echo add(1, ...$num); //6
 
上面的第二个和第三个参数将会从$num中循环赋值($b为2,$c为3)。
 
手册地址:http://php.net/manual/zh/migra ... s.php

相似文档查找算法之 simHash

专业名词zkbhj 发表了文章 • 0 个评论 • 111 次浏览 • 2018-09-05 14:50 • 来自相关话题

  积累工作学习中常用或者不常用的专业名词解释,方便查阅和学习。