DateTime类的常见用法

  • 初始化
1
2
3
4
//默认为当前时间
$tz = new DateTimezone('Asia/Shanghai');
echo (new DateTime('now', $tz))->format('Y-m-d H:i:s'); //2014-12-04 12:04:55
$d = new DateTime('+1 day', $tz); //2014-12-05 12:04:55
  • 设置时区

    1
    2
    $d = new DateTime(null, new DateTimezone('Asia/Shanghai'));
    $d->setTimezone('Asia/Shanghai');
  • 设置/获取时间戳

    1
    2
    echo $d->getTimestamp(); //1417664087
    echo $d->setTimestamp(1417664087)->format('Y-m-d H:i:s'); //2014-12-04 11:34:47
  • 修改时间

    1
    2
    3
    //明天当前时间 (使用关键字day、week、month year 进行修改)
    使用modify
    echo $d->modify('+1 day')->setTime(0, 0, 0)->format('Y-m-d H:i:s');

或者使用 sub、add

1
2
echo $d->sub(new DateInterval('P1D'))->format('Y-m-d H:i:s');
echo $d->add(new DateInterval('P1D'))->format('Y-m-d H:i:s');

  • 比较日期大小

    1
    2
    3
    4
    5
    $t = new DateTimezone('Asia/Shanghai');
    $d1 = new DateTime('2014-12-01', $t);
    $d2 = new DateTime('2014-12-02', $t);
    echo $d1 > $d2 ? 'd1 bigger than d2' : 'd1 less than d2';
  • 获取日期间的差异

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    $diff = $d1->diff($d2);
    print_r($diff);
    DateInterval Object
    (
    [y] => 0
    [m] => 0
    [d] => 1
    [h] => 0
    [i] => 0
    [s] => 0
    [weekday] => 0
    [weekday_behavior] => 0
    [first_last_day_of] => 0
    [invert] => 0
    [days] => 1
    [special_type] => 0
    [special_amount] => 0
    [have_weekday_relative] => 0
    [have_special_relative] => 0
    )

mongodb注入攻击

一直以为注入只存在关系型数据库中,看了这篇文章才知道mongodb也会中招.
翻看php手册发现早就发现有这个问题,以前看手册一直没注意.

数组绑定时的注入

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
<?php
$mongo = new mongoclient();
//选择数据库
$db = $mongo->myinfo;
//选择集合
$coll = $db->test;
$username = $_GET['username'];
$password = $_GET['password'];
$data = array(
'username'=>$username,
'password'=>$password
);
$data = $coll->find($data);
$count = $data->count();
if ($count>0) {
foreach ($data as $user) {
echo 'username:'.$user['username']."</br>";
echo 'password:'.$user['password']."</br>";
}
}
else{
echo '未找到';
}
?>

如果传入url为

1
http://127.0.0.1/2.php?username[$ne]=test&password[$ne]=test

mongodb最终执行:

1
db.test.find({username:{'$ne':'test'},password:{'$ne':'test'}});

php会把test集合内的所有数据全部便利出来。

防止注入的方法也很简单, 注意参数的检验.

1
2
3
4
5
6
7
8
9
<?php
...
$username = $_GET['username'];
$password = $_GET['password'];
$username = is_string($username) ? $username : '';
$password = is_string($password) ? $password : '';
...
?>

接受参数拼接直接以命令行执行的注入可以参考php手册 使用MongoCode 进行转椅后再使用.

curl的https问题

php 使用curl访问https网站时遇到的问题。
代码如下

1
2
3
4
5
6
7
8
9
10
<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
$return = curl_exec($ch);
curl_close($ch);
var_dump($return);
?>

返回false

修改代码 在curl_exec 后加入

1
2
3
if(curl_errno($ch)){
var_dump(curl_error($ch));
}

可以看到 证书获取不到的提示信息

SSL certificate problem: unable to get local issuer certificate

  • 简单解决 加入一下选项 禁用证书检查
    1
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  • 添加证书解决

    1. 获取证书

      1. 在浏览器(firefox)打开请求的接口地址,
      2. 选择菜单(工具–查看页面信息)
      3. 安全–查看证书–详细信息–选择顶级证书机构–导出(X.509(pem))
2. 修改代码 添加如下选项
1
2
3
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . '/BuiltinObjectToken-EquifaxSecureCA.crt');

SSL CA cert (path? access rights?) 问题 参考stackoverflow直接重启php-fpm

api签名

为了提高传输过程参数的防篡改性,必须使用签名参数sig.
本文只是一个签名的简单实现 验证参数完整性 请求超时.

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
41
42
43
44
45
46
47
48
49
50
51
52
<?php
class SomeClass
{
CONST API_PUBLIC_KEY = "asdadasdaxxxx";
CONST URL = 'http://example.com/api/';
public function signature(array $param,
$timeOut = 60)
{
$param['expire'] = time() + $timeOut;
$param['sig'] = hash_hmac('sha256',
join('', $param), self::API_PUBLIC_KEY);
$this->param = $param;
return $this;
}
public function getRequestUrl()
{
return self::URL . '?' . http_build_query($this->param);
}
public function validateSignature($param, $sig)
{
return hash_hmac('sha256', join('', $param), self::API_PUBLIC_KEY)
== $sig;
}
}
$obj = new SomeClass();
$param = array('useranme' => 'zhangsan');
//http://example.com/api/?useranme=zhangsan&expire=1408628093&sig=27b11880e19691b7e110cc8665c55160fc2b321b74c33b4877fac2da0545640e
echo $obj->signature($param, 300)->getRequestUrl();
$sig = isset($_GET['sig']) ? $_GET['sig'] : '';
$expire = isset($_GET['expire']) ? $_GET['expire'] : '';
if(!$obj->validateSignature($param, $sig)){
echo "签名验证错误";
exit;
}
if($expire < time()) {
echo "请求超时";
exit;
}
echo "processing";
?>

检查文档是否存在

<?php
    $mongo = new MongoClient();
    $db = $mongo->dbName;
    $collection = $db->collectionName;

    $cursor = $collection->find(
        $criteria, 
        array('_id' => 1)
    )->limit(1);

    if($coursor->count() == 0){
      exit('not exist');
    }

    exit('exits');