kk Blog —— 通用基础


date [-d @int|str] [+%s|"+%F %T"]
netstat -ltunp

PHP session有效期session.gc_maxlifetime

https://www.jb51.net/article/26890.htm

PHP中的session有效期默认是1440秒(24分钟)【weiweiok 注:php5里默认的是180分】,也就是说,客户端超过24分钟没有刷新,当前session就会失效。很明显,这是不能满足需要的。

服务器的操作,只是需要进行如下的步骤:

1、把“session.use_cookies”设置为1,打开Cookie储存SessionID,不过默认就是1,一般不用修改;

2、把“session.cookie_lifetime”改为正无穷(当然没有正无穷的参数,不过999999999和正无穷也没有什么区别);

3、把“session.gc_maxlifetime”设置为和“session.cookie_lifetime”一样的时间;

在PHP的文档中明确指出,设定session有效期的参数是session.gc_maxlifetime。可以在php.ini文件中,或者通过ini_set()函数来修改这一参数。

PHP 使用 +1month、-1month 的问题

https://blog.csdn.net/qq_32737755/article/details/92690573

经常会有人被strtotime结合-1 month, +1 month, next month的时候搞得很困惑, 然后就会觉得这个函数有点不那么靠谱, 动不动就出问题. 用的时候就会很慌…

比如 2018-07-31 这天执行代码:

1
date("Y-m-d",strtotime("-1 month"))

怎么输出是的2018-07-01? 上个月的最后一天不应该是2018-06-30吗?

我们来模拟下date内部的对于这种事情的处理逻辑:

1
2
1. 先做-1 month, 那么当前是07-31, 减去一以后就是06-31.
2. 再做日期规范化, 因为6月没有31号, 所以就好像2点60等于3点一样, 6月31就等于了7月1

怎么办

只用每月1号处理

从PHP5.3开始呢, date新增了一系列修正短语, 来明确这个问题, 那就是”first day of” 和 “last day of”, 也就是你可以限定好不要让date自动”规范化”:

1
2
3
4
var_dump(date("Y-m-d", strtotime("last day of -1 month", strtotime("2017-03-31"))));
//输出2017-02-28
var_dump(date("Y-m-d", strtotime("first day of +1 month", strtotime("2017-08-31"))));
输出2017-09-01

vpn CONNECT方法

https://www.cnblogs.com/xyl1932432873/p/7735866.html

CONNECT这个方法的作用就是把服务器作为跳板,让服务器代替用户去访问其它网页,之后把数据原原本本的返回给用户。这样用户就可以访问到一些只有服务器上才能访问到的网站了,这就是HTTP代理。

假如我想通过代理访问这个博客(www.web-tinker.com),我就需要建立一个TCP连接,连接到服务器监听的那个端口,然后给服务器发送一个HTTP头。下面就是这个HTTP头的内容:

1
2
3
4
5
CONNECT www.web-tinker.com:80 HTTP/1.1
Host: www.web-tinker.com:80
Proxy-Connection: Keep-Alive
Proxy-Authorization: Basic *
Content-Length: 0

所有的HTTP头都是类似的,第一行是方法名、主要参数、HTTP版本。接着一行一个参数,最后用两个换行来结束。这个地方应该填写验证的用户名和密码。

发送完这个请求之后,就是服务器端响应请求了。如果用户名和密码验证通过,就会返回一个状态码为200的响应信息。虽然状态码是200,但是这个状态描述不是OK,而是Connection Established。

1
HTTP/1.1 200 Connection Established

如果用户名和密码验证不通过。会返回一个407的状态码,状态表述是Unauthorized。表示没有权限访问代理服务器。

1
HTTP/1.1 407 Unauthorized

验证通过之后,我们就可以做普通的HTTP操作了。完全可以把现在的代理服务器看作是请求连接的Internet服务器,也就是说可以像直接访问普通的服务器一样,使用GET、POST等方法来请求Internet服务器上的页面了。我们在发送CONNECT请求的时候就已经告诉了服务器我们需要访问的Internet服务器,上面我用了这个博客的网址。现在我们要访问这个博客的主页就可以发送一个简单的GET请求。

1
2
3
GET / HTTP/1.1
Host: www.web-tinker.com
Content-Length: 0

微信公众号获取OpenId(未授权)(需要关注公众号)

https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html

https://blog.csdn.net/HanKin_/article/details/79010789

openId是微信对于用户的唯一辨识,只要有用户关注你的公众号,微信会通过公众号和用户微信号通过一种算法生成一种唯一标识码

1.在公众号后台设置回调的域名(大多情况下是你的项目)

开发-接口权限-网页账号-用户授权获取用户基础信息中修改

2.在页面上访问下面的网址

1
https://open.weixin.qq.com/connect/oauth2/authorize?appid=*******&redirect_uri=你回调的地址&response_type=code&scope=snsapi_base&state=1#wechat_redirect

上面的会返回到你回调的地址?code=xxxxxxxxx

也就是说它会返回到你回调的地址并且带上code参数,一般情况下,回调的地址设置为后端的action即可,然后就可以获取到code了,当你获取到code,已经成功了一大半。

3.然后在后端访问下面的网址

1
https://api.weixin.qq.com/sns/oauth2/access_token?appid=***&secret=***&code=***&grant_type=authorization_code

code的参数用刚刚返回的code值。

4.上面网页将会返回json,其中openId就在其中。

至此,openId就获取到了,但是要注意:此处只获取到了openId,也就是不需要用户授权的,要获取用户其它的信息请参考接口文档。还有就是每次获取openId请重新获取code,code值不要重复使用,防止出错。

在微信页面上我是把获取到的openId保存在cookie中的,这样就可以防止openId的重复获取,我只在用户第一次进入或者cookie中的openId失效的时候进行再次获取的。


code

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
<?php
class Wxmsg extends CI_Controller {
	function __construct()
	{
		parent::__construct();
		$this->load->model('Follow_model');
		$this->load->helper('url');
		$this->load->helper('xml');
	}

	function index($check = 1)
	{
		$echostr = $this->input->get('echostr');
		if (!empty($echostr)) {
			echo $echostr;
			return;
		}

		$token = "hello";

		# step 1: get args
		$slug = array('signature', 'timestamp', 'nonce', 'openid');
		foreach ($slug as $key) {
			$args[$key] = $this->input->get($key);
			if ($check && empty($args[$key]))
				die($key.' 不能为空');
		}

		# step 2: signature check
		$lists = array($args['timestamp'], $args['nonce'], $token);
		sort($lists, SORT_STRING);
		$hashcode = sha1(implode('', $lists));
		if ($check && $hashcode != $args['signature'])
			die('signature 校验错误');

		# step 3: webdata decode
		$webdata = $this->input->raw_input_stream;
		$xml = simplexml_load_string($webdata);
		foreach ($xml->children() as $child) {
			$arr[$child->getName()] = trim((string)$child);
		}

		if (empty($arr['FromUserName']) || empty($arr['ToUserName']))
			die('FromUserName、ToUserName 不能为空');

		if (empty($arr['MsgType']))
			die('MsgType 不能为空');

		if ($arr['MsgType'] == 'text') {
			if (empty($arr['CreateTime']) || empty($arr['Content']) || empty($arr['MsgId']))
				die('CreateTime、Content、MsgId 不能为空');

			# step 4.1 text msg
			$Content = self::msg_text($arr);

		} elseif ($arr['MsgType'] == 'event') {
			if (empty($arr['Event']))
				die('Event 不能为空');

			# step 4.2 event msg
			$Content = self::msg_event($arr);

		} else {
			die('不处理事件:'.$arr['MsgType']);
		}

		self::reply_msg($arr, $Content);
	}

	function reply_msg($arr, $Content)
	{
		$FromUserName = $arr['FromUserName'];
		$ToUserName = $arr['ToUserName'];
		$CreateTime = time();
		$reply =
<<<XML
	<xml>
		<ToUserName><![CDATA[$FromUserName]]></ToUserName>
		<FromUserName><![CDATA[$ToUserName]]></FromUserName>
		<CreateTime>$CreateTime</CreateTime>
		<MsgType><![CDATA[text]]></MsgType>
		<Content><![CDATA[$Content]]></Content>
	</xml>
XML;
		$reply_xml = new SimpleXMLElement($reply);
		echo $reply_xml->asXML();
	}

	function msg_text($arr)
	{
		$FromUserName = $arr['FromUserName'];
		$key = $arr['Content'];

		$Content = '萌萌嗒';
		return $Content;
	}

	function msg_event($arr)
	{
		$event = $arr['Event'];
		if ($event == 'subscribe') {
			$this->Follow_model->change($arr['FromUserName'], $arr['ToUserName'], 1);
			return "功能添加中\n敬请等待\n";
			#return '输入姓名或电话查询单号,输入单号查询物流信息';
		} elseif ($event == 'unsubscribe') {
			$this->Follow_model->change($arr['FromUserName'], $arr['ToUserName'], 0);
		}
		return '';
	}

	function test()
	{
		$openid = $this->input->ip_address();

		$openid = $this->input->cookie("openid");
		if (empty($openid)) {
			$appid = appId;
			$redirect_uri = "http://".HOST.ROOT."/wxmsg/openid";
			$URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=$appid&redirect_uri=$redirect_uri&response_type=code&scope=snsapi_base&state=1#wechat_redirect";
			redirect($URL);
		}

		echo "test";
	}

	function openid()
	{
		$code = $this->input->get('code');
		if (empty($code)) {
			die('无法获取code');
		}
		//echo $code;
		#$fp = fopen('/tmp/a.txt', 'w');
		#fwrite($fp, $code);

		$appid = appId;
		$secret = appSecret;
		$URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appid&secret=$secret&code=$code&grant_type=authorization_code";

		$furl = fopen($URL, 'r') or exit('Open url faild!');
		$res = fgets($furl);
		fclose($furl);

		$res = json_decode($res, True);

//        var_dump($res);
//        echo $res['openid'];

		if (empty($res['openid'])) {
			die('无法获取openid');
		}
		$this->input->set_cookie('openid', $res['openid'], 86400 * 7);

		$URL = ROOT."/wxmsg/test";
		redirect($URL);
	}
}