微信小程序 服务器端生成用户登陆环节的 3rd_session
一、环境:
CentOS 6.8
nginx 1.8.0
php 7.0.10
二、背景
最近在开发一个微信小程序,不可避免的涉及到登陆的环节,登录时序图如下:
通过 wx.login() 获取到用户登录态之后,需要维护登录态。开发者要注意不应该直接把 session_key、openid 等字段作为用户的标识或者 session 的标识,而应该自己派发一个session 登录态。
—— 微信官方文档(https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-login.html#wxchecksessionobject)
所以,我们要给服务器上的 session 登录态设定一个 key 值,key 值就是本文说的 3rd_session。
三、正文
下面就是生成 3rd_session 的方法了,具体代码的解释可以看注释和上文的登录时序图对 3rd_session 的要求,就不赘述了。
function _3rd_session($len)
{
$fp = @fopen('/dev/urandom', 'rb');
$result = '';
if ($fp !== FALSE) {
$result .= @fread($fp, $len);
@fclose($fp);
} else {
trigger_error('Can not open /dev/urandom.');
}
// convert from binary to string
$result = base64_encode($result);
// remove none url chars
$result = strtr($result, '+/', '-_');
return substr($result, 0, $len);
}
echo _3rd_session(16);
四、遇到的问题
1、@fopen('/dev/urandom', 'rb') 的时候,报错 "Can not open /dev/urandom"
说明 fopen('/dev/urandom', 'rb') 没有成功打开文件,一般有三种原因:
1、路径不对
2、文件不存在
3、没有权限
1/2、路径不对 /文件不存在
如果 /dev/
里没有 urandom
和 random
文件(必须两者同时存在),可以用下面方法生成这两个文件:
mknod -m 644 /dev/random c 1 8
mknod -m 644 /dev/urandom c 1 9
chown root:root /dev/random /dev/urandom
3、没有权限
如果有这两个文件存在,且你的接口所在项目的权限也没问题的时候,可能是 php 的访问权限造成的:
open_basedir
是 控制 php 访问路径权限的属性。
我查看了我的 php.ini
,果然没有包含 /dev/
:
于是我修改了 php.ini
的 open_basedir
值,并重启了 php:
service php-fpm restart
再次打开 php.ini
,哪尼? open_basedir
的值根本没变。
原来,是 nginx 的设置插了一脚。
在 nginx 的 nginx.conf
中的某个 server 中:
location ~ \.php($|/) {
fastcgi_pass unix:/dev/shm/php-cgi.sock;
fastcgi_index index.php;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PHP_VALUE "open_basedir=$document_root:/tmp/";
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
把倒数第三行中的 open_basedir
添加上 /dev/
路径,即为:
fastcgi_param PHP_VALUE "open_basedir=$document_root:/tmp/:/dev/";
完美。
五、知识点
(1)为什么在 '/dev/urandom' 里取随机数?
微信的官方文档推荐用这种操作系统提供真正随机数的方法。而不是
srand(当前时间) 然后 rand() 的方法。
(2)'/dev/urandom' 是真的随机数?
其实绝对随机的随机数只是一种理想的随机数,即使计算机怎样发展,它也不会产生一串绝对随机的随机数。
但是 '/dev/urandom' 和 '/dev/random' 已经算是很接近真随机数的随机数了。
他们的原理是,数据通常来自于设备驱动程序。例如,键盘驱动程序收集两个按键之间时间的信息,然后将这个环境噪声填入随机数发生器库。
linux 内核维护了一个熵池用来收集来自设备驱动程序和其它来源的环境噪音,它在每次有新数据进入时进行“搅拌” 。使得更随机。
(3)'/dev/random' 和 '/dev/urandom' 有什么区别?
因为熵池中返回的随机数依赖于外部,'/dev/random' 往往被取出过快导致熵池里没有剩余可用的随机数。
但是 '/dev/urandom' 仍可以从熵池的 MD5 散列中获得非常好的随机数,所以为了程序的健壮性,推荐使用 '/dev/urandom'。
但是 '/dev/random' 会比 '/dev/urandom' 安全,因为后者依赖MD5,会存在被破译的风险。