0%

你这么擅长安慰他人,一定度过了很多自己安慰自己的日子吧

基本概念

CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
那么CSRF到底能够干嘛呢?你可以这样简单的理解:攻击者可以盗用你的登陆信息,以你的身份模拟发送各种请求。攻击者只要借助少许的社会工程学的诡计,例如通过QQ等聊天软件发送的链接(有些还伪装成短域名,用户无法分辨),攻击者就能迫使Web应用的用户去执行攻击者预设的操作。例如,当用户登录网络银行去查看其存款余额,在他没有退出时,就点击了一个QQ好友发来的链接,那么该用户银行帐户中的资金就有可能被转移到攻击者指定的帐户中。
所以遇到CSRF攻击时,将对终端用户的数据和操作指令构成严重的威胁;当受攻击的终端用户具有管理员帐户的时候,CSRF攻击将危及整个Web应用程序。

CSRF的攻击过程

要完成一次CSRF攻击,受害者必须依次完成两个步骤 :
1.登录受信任网站A,并在本地生成Cookie 。
2.在不退出A的情况下,访问危险网站B。
看到这里,读者也许会问:“如果我不满足以上两个条件中的任意一个,就不会受到CSRF的攻击”。是的,确实如此,但你不能保证以下情况不会发生:
你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站,特别现在浏览器都是支持多tab的。
你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。
上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。
因此对于用户来说很难避免在登陆一个网站之后不点击一些链接进行其他操作,所以随时可能成为CSRF的受害者。
CSRF攻击主要是因为Web的隐式身份验证机制,Web的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的

如何预防CSRF

CSRF的防御可以从服务端和客户端两方面着手,防御效果是从服务端着手效果比较好,现在一般的CSRF防御也都在服务端进行。
服务端的预防CSRF攻击的方式方法有多种,但思想上都是差不多的,主要从以下2个方面入手:
1、正确使用GET,POST和Cookie;
2、在非GET请求中增加伪随机数;

为每个用户生成一个唯一的cookie token,所有表单都包含同一个伪随机值,这种方案最简单,因为攻击者不能获得第三方的Cookie(理论上),所以表单中的数据也就构造失败,但是由于用户的Cookie很容易由于网站的XSS漏洞而被盗取,所以这个方案必须要在没有XSS的情况下才安全。
每个请求使用验证码,这个方案是完美的,因为要多次输入验证码,所以用户友好性很差,所以不适合实际运用。
不同的表单包含一个不同的伪随机值,我们在4.4小节介绍“如何防止表单多次递交”时介绍过此方案,复用相关代码,实现如下:

生活总是有很多出人意料的事情,比如,你以为我要举个例子。

应用前提

1
2
3
4
5
分支里面的代码如果没有提交commit ,那么切换到其他分支下还是可以看
到(git status)这个分支下的代码.

但是如果我们现在想要切换到别的分支但是同时又不想提交commit我们的代码
该如何处理?

git stash

1
2
3
在你切换分支前,运行:git stash 就可以了
当你在其他分支改好了代码并切换回当前分支的时候,请git stash pop

相关命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
git stash
保存当前的工作进度。会分别对暂存区和工作区的状态进行保存

git stash save "message..."
这条命令实际上是第一条 git stash 命令的完整版

git stash list
显示进度列表。此命令显然暗示了git stash 可以多次保存工作进度,并用在恢复时候进行选择

git stash pop [--index] [<stash>]
如果不使用任何参数,会恢复最新保存的工作进度,
并将恢复的工作进度从存储的工作进度列表中清除。
如果提供参数(来自 git stash list 显示的列表),则从该 <stash> 中恢复。恢复完毕也将从进度列表中删除 <stash>。
选项--index 除了恢复工作区的文件外,还尝试恢复暂存区。

git stash apply [--index] [<stash>]
除了不删除恢复的进度之外,其余和 git stash pop 命令一样

git stash clear
删除所有存储的进度

某天,你无端想起一个人,她曾让你对明天有所期许,但是却完全没有出现在你的明天里。

简要说明

1
2
3
4
5
6
7
8
一个高性能的支持丰富数据结构的 NoSQL 数据库, 用于替代 Redis.
基于google/leveldb 开发SSDB是一个开源的高性能数据库服务器,
使用Google 的 LevelDB作为存储引擎, 大家有可能没听过leveldb的名字,
但是淘宝的开源nosql tair大家应该有所耳闻吧,他也是基于leveldb做的开发。
ssdb支持T级别的数据, 同时支持类似Redis中的zset和hash等数据结构,
在同时需求高性能和大数据的条件下, 是一个可以代替Redis的方案.
ssdb是一个持久化存储的KV系统,和Memcached、Redis这种内存型的KV系统不同,
ssdb不会像Redis一样狂吃内存,而是将大部分数据存储到磁盘上。

安装

1
2
3
4
5
6
wget --no-check-certificate https://github.com/ideawu/ssdb/archive/master.zip
unzip master
cd ssdb-master
make
# optional, install ssdb in /usr/local/ssdb
sudo make install

启动

1
2
3
4
5
# start master
./ssdb-server ssdb.conf

# or start as daemon
./ssdb-server -d ssdb.conf

使用

1
2
3
4
5
6
<?php
require_once('SSDB.php');
$ssdb = new SimpleSSDB('127.0.0.1', 8888);
$resp = $ssdb->set('key', '123');
$resp = $ssdb->get('key');
echo $resp; // output: 123

关于leveldb

1
2
3
4
LevelDB是google开源的一个key-value存储引擎库,类似于开源的Lucene索引库一样。
其他的软件开发者可以利用该库做二次开发,来满足定制需求。
LevelDB采用日志式的写方式来提高写性能,但是牺牲了部分读性能。
为了弥补牺牲了的读性能,一些人提议使用SSD作为存储介质。

说明

1
2
修改ssdb.conf文件,把ip改成0.0.0.0,允许外网访问
高级应用可以查看主从这一块儿

http://ssdb.io/zh_cn/

“跑呀跑呀跑呀跑呀,拼命努力着追上前面那个被目光期许的自己,生怕抓不住时光,只有和你一起的时候,才觉得不如就这样老了吧,也不算太辜负。”
### CGI
1
2
3
4
5
6
7
8
9
CGI英文全程是 Command Gateway Interface,通常翻译为公共网关接口,
HTTP服务器与机器上的其他程序进行通信的一个接口。
这个“其他程序”可以是使用任何计算机语言进行编 写,例如phppythonperl等等。
它通过CGI这个接口从HTTP服务器取得输入,然后把运行结果又通过CGI这个接口交给HTTP服务器, 而HTTP服务器把这个结果送给浏览器。

CGI 的出现让WEB从静态变为动态,随着web的越来越普及,很多的网站都需要有动态的页面,
以便与浏览者进行交互。CGI的缺点也越来越突出,因为HTTP 要生成一个动态页面,
系统就必须启动一个新的进程以运行CGI程序,
不断的fork是一项很消耗时间和资源的工作。

FastCGI

1
2
3
4
5
6
7
8
FastCGIFastCGI是可伸缩架构的CGI开放扩展,
其主要行为是将CGI解释器进程保持在内存中并因此获得较高的性能。
传统的CGI 解释器的反复加载是CGI性能低下的主要原因,
如果CGI解释器保持在内存中并接受FastCGI进程管理器调度,
则可以提供良好的性能、伸缩性等 。在上述情况中,你可以想象 CGI通常有多慢。
每一个Web请求PHP都必须重新解析php.ini、重新载入全部扩展并重初始化全部数据结构。
使用FastCGI,所有这些 都只在进程启动时发生一次。一个额外的好处是,
持续数据库连接(Persistent database connection)可以工作。

mod_php

1
2
3
4
5
6
7
8
9
10
11
12
在lamp体系中,对于apache端的php的配置,我们最常用的就是mod_php,
它把php作为apache一个内置的模块.让apache http服务器本身能够支持php语言,
不需要每一个请求就启动php解释器来解释php.

和把webserver与php绑定起来的方式不同,
fastcgi是http服务器与你的或其它机器上的程序进行“交谈”的一种工具,
相当于一 个程序接口。它可以接受来自web服务器的请求,解释输入信息,
将处理后的结果返回给服务器等。mod_fastcgi就是在apache下支持 fastcgi协议的模块。

在lamp体系中,mod_php是最常使用的工作方式。在这种模式下,
php被编译为apache的一个内置模块,在启动加载的时候,
当有一个php请求过来,直接在httpd进程里完成了php的解释运行,将结果返回。

mod_fastcgi

1
2
3
4
mod_fastcgi就是在apache下支持 fastcgi协议的模块。
fastcgi实例和apache分离开来,这两者可以分开来部署。
他们之间的通信通过tcp或者unix sock来完成。使用ext方式,
fastcgi实例是独立运行的。

FPM

1
2
3
FPM(FastCGI 进程管理器)用于替换 PHP FastCGI 的大部分附加功能,
对于高负载网站是非常有用的。

http://blog.shiliuvip.com/391.html
http://php.net/manual/zh/install.fpm.php

最初不相识,最终不相认
生成器允许你在 foreach 代码块中写代码来迭代一组数据而不需要在内存中创建一个数组, 那会使你的内存达到上限,或者会占据可观的处理时间。相反,你可以写一个生成器函数,就像一个普通的自定义函数一样, 和普通函数只返回一次不同的是, 生成器可以根据需要 yield 多次,以便生成需要迭代的值。 一个简单的例子就是使用生成器来重新实现 range() 函数。 标准的 range() 函数需要在内存中生成一个数组包含每一个在它范围内的值,然后返回该数组, 结果就是会产生多个很大的数组。 比如,调用 range(0, 1000000) 将导致内存占用超过 100 MB。 做为一种替代方法, 我们可以实现一个 xrange() 生成器, 只需要足够的内存来创建 Iterator 对象并在内部跟踪生成器的当前状态,这样只需要不到1K字节的内存。 ### 简单理解
1
2
3
4
5
6
官方的定义中:生成器就是简单的迭代器。
不同于标准的PHP迭代器,PHP的生成器并不要求你一定要在一个重量级的类中实现Iterator接口。
相反,生成器会按需求计算并交出迭代值。这对应用程序的性能有着深远的意义。想想吧,
一个标准的PHP迭代器通常都是基于内存中全部计算过的数据集进行迭代。这样做效率不高。
尤其是大量可计算的公式化数据集。使用生成器我们可以动态的计算并交出下一个值而不占用
宝贵的系统内存,这就是我们使用生成器的原因。
### 创建一个生成器
1
2
3
4
5
6
<?php  
function myGenerator() {
yield 'value1';
yield 'value2';
yield 'value3';
}
### 使用这个生成器
1
2
3
4
<?php  
foreach (myGenerator() as $yieldedValue) {
echo $yieldedValue, PHP_EOL;
}
结果: value1 value2 value3

实例

  • Range生成器(糟糕的实现)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php  
function makeRange($length) {
$dataset = [];
for ($i = 0; $i < $length; $i++) {
$dataset[] = $i;
}

return $dataset;
}

$customRange = makeRange(1000000);
foreach ($customRange as $i) {
echo $i, PHP_EOL;
}

  • Range生成器(好的实现)
1
2
3
4
5
6
7
8
9
10
11
<?php  
function makeRange($length) {
for ($i = 0; $i < $length; $i++) {
yield $i;
}
}

foreach (makeRange(1000000) as $i) {
echo $i, PHP_EOL;
}

上面的例子并不实用。但是,联想一下所有你可能用来计算的数据集。序列数(例如斐波纳挈数)就是很典型的例子。同样你还可以遍历文件流资源。想象一下,如果你需要遍历一个4G的逗号分隔值(CSV)文件,而你的虚拟个人服务器(VPS)上PHP只分配了1G的内存。你根本没法把整个文件读取到内存中。

  • CSV生成器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php  
function getRows($file) {
$handle = fopen($file, 'rb');
if ($handle === false) {
throw new Exception();
}
while (feof($handle) === false) {
yield fgetcsv($handle);
}
fclose($handle);
}

foreach (getRows('data.csv') as $row) {
print_r($row);
}

接收参数

1
2
3
4
5
6
7
8
9
10
11
function printer()
{
while (true) {
printf("receive: %s\n", yield);
}
}

$printer = printer();

$printer->send('hello');
$printer->send('world');

说明

生成器的确使用了很少的内存却大大简化了某些任务。如果你需要更强大的功能诸如重置、快进、或者数据集的检索,你最好还是自定义一个实现Iterator interface接口的类,或者使用PHP现成的Standard PHP Library(SPL)迭代器。

yieldreturn 都会返回值,但区别在于一个 return 是返回既定结果,一次返回完毕就不再返回新的结果,而 yield 是不断产出直到无法产出为止。

http://blog.csdn.net/bandita/article/details/47723815
https://laravel-china.org/articles/1430/single-php-generator-complete-knowledge-generator-implementation-process

最孤独的,不是不能跟一个人在一起,而是根本不知道想跟谁在一起......

说明

PHP5开始支持了接口, 并且内置了Iterator接口, 所以如果你定义了一个类,并实现了Iterator接口,
那么你的这个类对象就是ZEND_ITER_OBJECT,否则就是ZEND_ITER_PLAIN_OBJECT.
对于ZEND_ITER_PLAIN_OBJECT的类,foreach会通过HASH_OF获取该对象的默认属性数组,然后对该数组进行foreach.
而对于END_ITER_OBJECT的类对象,则会通过调用对象实现的Iterator接口相关函数来进行foreach。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php

/**
* Iterator模式的简单实现类
*/
class sample implements Iterator {
private $_items ;

public function __construct(&$data) {
$this->_items = $data;
}
public function current() {
return current($this->_items);
}

public function next() {
next($this->_items);
}

public function key() {
return key($this->_items);
}

public function rewind() {
reset($this->_items);
}

public function valid() {
return ($this->current() !== FALSE);
}
}

/** DEMO */
$data = array(1, 2, 3, 4, 5);
$sa = new sample($data);
foreach ($sa AS $key => $row) {
echo $key, ' ', $row, '<br />';
}

?>

适用范围

  • 使用返回迭代器的包或库时(如PHP5中的SPL迭代器)
  • 无法在一次的调用获取容器的所有元素时
  • 要处理数量巨大的无素时(数据库中的表以GB计的数据)
  • ……

举例

一般是使用foreach来使用迭代器,下面整理了一下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php   
class sample implements Iterator
{
private $_items = array(1,2,3,4,5,6,7);

public function __construct() {
;//void
}
public function rewind() { reset($this->_items); }
public function current() { return current($this->_items); }
public function key() { return key($this->_items); }
public function next() { return next($this->_items); }
public function valid() { return ( $this->current() !== false ); }
}

$sa = new sample();
foreach($sa as $key => $val){
print $key . "=>" .$val;
}
?>

我做事三分钟热度,却也爱你那么久。
### 问题
1
使对象可以像数组一样进行foreach循环,要求属性必须是私有。

鸟哥给出的答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class sample implements Iterator
{
private $_items = array(1,2,3,4,5,6,7);

public function __construct() {
;//void
}
public function rewind()
{
reset($this->_items);
}
public function current()
{
return current($this->_items);
}
public function key()
{
return key($this->_items);
}
public function next()
{
return next($this->_items);
}
public function valid()
{
return ( $this->current() !== false );
}
}

$sa = new sample();
foreach($sa as $key => $val){
print $key . "=>" .$val.'<br>';
}

拓展说明

使用foreach只可以循环出数组的public属性,protected和private属性无法得到

1
2
3
4
5
6
7
8
9
10
11
12
13
class User
{
public $a = 'tom';
protected $b = 'lilei';
private $c = 'hanmeimei';
public function __construct()
{
}
}

foreach (new User() as $user){
echo $user.'<br>';
}

但是在类的内部可以

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class User
{
public $a = 'tom';
protected $b = 'lilei';
private $c = 'hanmeimei';
public function do_something() {
foreach($this as $key => $value) {
echo "$key => $value\n";
}
}
}

$user = new User();
$user->do_something();

http://www.laruence.com/2008/10/31/574.html

你走了好,不然总担心你要走。
### 实验环境 - laravel 5.1

实验步骤

  • 1.安装扩展包
1
composer require rcrowe/twigbridge
  • 2.在config/app.php下配置
1
2
3
4
5
6
7
8
'providers' => [
...
TwigBridge\ServiceProvider::class,
],
'aliases' => [
...
'Twig' => TwigBridge\Facade\Twig::class,
],
  • 3.发布配置文件,该操作会在config目录下新建一个专属twig的配置文件twigbrage.php
1
php artisan vendor:publish --provider="TwigBridge\ServiceProvider"
  • 4.开始使用
1
2
3
4
5
6
7
8
9
10
11
//返回视图
Route::get('test',function (){
$users = \App\User::all();
return view('hello',compact('users'));
});
//新建视图文件resources/views/hello.twig
<body>
{% for user in users %}
{{ user.name }}
{% endfor %}
</body>

参考

https://packagist.org/packages/rcrowe/twigbridge

答案很长,我准备用一生的时间来回答,你准备要听了吗?

简介

1
2
3
4
5
6
7
MySQL的内存表,表结构创建在磁盘上,数据存放在内存中,所以当MySQL启动着的时候,
这个表是存在的,数据也是存在的,当MySQL重启后,数据消失,表结构还存在(
临时表表结构及数据都在内存中)。内存表最大所需内存需要通过
max_heap_table_size=1024M设定,临时表最大所需内存需要通过tmp_table_size = 1024M
设定。当数据超过临时表的最大值设定时,自动转为基于磁盘的MyISAM表,
存储在指定的tmpdir目录,此时因需要进行IO操作,性能会大大下降,
而内存表不会,内存表满后,会提示数据满错误。

特征

1
2
3
4
内存表的表定义是存放在磁盘上的,扩展名为.frm, 重启不会丢失。
内存表的数据是存放在内存中的,重启会丢失数据。
MEMORY表使用一个固定的记录长度格式。
mysql重启后,主键、自增、索引仍然存在,只是数据丢失。

优点

1
内存表使用哈希散列索引把数据保存在内存中,因此具有极快的速度。

缺点

1
2
3
4
内存表不能包含BLOB或者TEXT列。
内存表不支持事务。
内存表是表锁,当修改频繁时,性能可能会下降。
内存表数据清空或删除表后占用内存不会自动释放。

基本操作

1
2
3
4
CREATE TABLE mem_table(  
id int(10),
num int(10)
) ENGINE=MEMORY;

她是你姑姑,又是你师父,怎么能做你妻子!

概念

ORM即Object/Relation Mapping的简写,一般称作“对象关系映射”,在Web开发中最常出没于和关系型数据库交互的地方。ORM以最基本的形式建模数据。比如ORM会将MySQL的一张表映射成一个PHP类(模型),表的字段就是这个类的成员变量

举例

在OOP中通常我们需要写一个对应的class User来作为user数据表的数据模型:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 声明class User
class User{
$id;
$name;

function create(){/*...*/}
function load($id){/*...*/}
}

// 使用class User
$user = new User();
$user->name = 'fancy';
$user->create();

但是通过ORM,我们可以不用去声明class User,可以直接继承ORM提供的工厂类,比如:

1
2
3
4
// 直接使用!对于熟悉MVC的亲知道这个意义之所在!
$user = new ORM('user'); // ORM都有自己的规则,这里直接使用了MySQL的表名
$user->name = 'fancy'; // MySQL的表的字段就是$user对象的成员变量
$user->save(); // 掉用ORM提供的接口函数

缺点

在某些复杂的sql中有性能问题