您正在查看: 技术Note 分类下的文章

php使用openssl来实现非对称加密签名,用于接口间安全传输数据

使用非对称加密主要是借助openssl的公钥和私钥,用公钥加密私钥解密,或者私钥加密公钥解密。
1.linux需要安装openssl和php的openssl扩展
2.生成私钥:openssl genrsa 用于生成rsa私钥文件,生成是可以指定私钥长度和密码保护


openssl genrsa -out rsa_private_key.pem 1024
3.生成公钥:rsa命令用于处理RSA密钥、格式转换和打印信息

openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem  
4.测试代码

<?php
//密钥
$secret = 'e10adc3949ba59abbe56e057f20f883e';

//测试数据
$_POST = array();
$_POST['id'] = 1;
$_POST['name'] = 'zhansan';

//生成签名
$sign = MakeSign($_POST, $secret);

$public_key = '-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAbfx4VggVVpcfCjzQ+nEiJ2DL
nRg3e2QdDf/m/qMvtqXi4xhwvbpHfaX46CzQznU8l9NJtF28pTSZSKnE/791MJfV
nucVcJcxRAEcpPprb8X3hfdxKEEYjOPAuVseewmO5cM+x7zi9FWbZ89uOp5sxjMn
lVjDaIczKTRx+7vn2wIDAQAB
-----END PUBLIC KEY-----';

//打印签名
echo $sign;
echo '<br>';

//利用公钥加密签名
openssl_public_encrypt($sign, $token, $public_key); 
//token为加密的sign,后面用私钥解密获取sign
$token = base64_encode($token);

//打印token
echo $token;
echo '<br>';

//rsa 私钥
$private_key='-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDAbfx4VggVVpcfCjzQ+nEiJ2DLnRg3e2QdDf/m/qMvtqXi4xhw
vbpHfaX46CzQznU8l9NJtF28pTSZSKnE/791MJfVnucVcJcxRAEcpPprb8X3hfdx
KEEYjOPAuVseewmO5cM+x7zi9FWbZ89uOp5sxjMnlVjDaIczKTRx+7vn2wIDAQAB
AoGAZzUWajxKTZeJqh5FjBgmwZi5M7voFynZAjRWAkCkqZye0FfY7e70kA92C1AL
aVqySnNr4WYZuGorEeOFGqHIv1XSowTLgfLkVBZ/SXiep2QYJrR0YevjysvLnTfb
mrdWCqWSj+0AlQg+AvDA/qtvBVMxKymbpo+4bj5H2pPPZ1ECQQDi1PwJQJBYPbpL
vGmP3AmWg467tCeQ+aJGgtQTOK5BH+p0BWFVDX583R437vllkKI8EXgZfqQfsQcj
7XUAXyZVAkEA2SyFbO8roH9JLrEoxxKGeiGZvhPfNl9nXLhX0OFS0ywQaVBJno39
9W5bX5iP5Jzeb3UWsZ/TxzhGc/b4WjAlbwJBAOFuIn1feRT5Y+hY++BJIg4/+N57
EMd4ENpas0HXFvcKLQvZPP42Rvr5FksoaRuTPmjMQ7uyrJICccI3AAy6g3ECQQDE
AyH9+zRmLNxRj0advsOvUcpgu7DYc21oS12/Qs+tl3TMiNGZkNDphwxjkOA217sP
4B92fCn6AnncSslHJXNzAkBo6ujxqIfrZMOG3ON9nXxkWlq39GFS6CzXWscHA3Xz
FMVT1WWU3FR2Kf2QSKiMGv02YcI2xfowim3JnT6600N0
-----END RSA PRIVATE KEY-----';




$token = base64_decode($token);
//利用私钥解密获取sigi签名
openssl_private_decrypt($token, $sign2, $private_key); 

//打印sign
echo $sign2;
echo '<br>';

if($sign2 == MakeSign($_POST, $secret)){
    exit('token校验成功');
}else{
    exit('token校验失败') ;
}




 /**
 * 生成签名
 * 备注:sign不参与签名
 * $data # 数组
 * $secret # 密钥
 */
function MakeSign($data = '', $secret = '')
{
    //签名步骤一:按字典序排序参数
    ksort($data);
    //签名步骤二:格式化成url参数
    $buff = "";
    foreach ($data as $k => $v)
    {
        if($k != "sign"){
            $buff .= $k . "=" . $v . "&";
        }
    }
    $string = trim($buff, "&");
    //签名步骤三:在string后加入KEY
    $string = $string . "&secret=".$secret;
    //签名步骤四:MD5加密
    $string = md5($string);
    //签名步骤五:所有字符转为大写
    $result = strtoupper($string);
    return $result;
}

测试结果

签名
AB1FAD5119B796DD87FAF8C88D57EF86
加密后的签名用于传输
sEHmlQqxShwDYcoEEDwIh7Aa7BYDbvOQmVUqlPppwWLpta4+Xxb+GTaQopsuKBgQ1sJgQahuOjvohHuSgj9tRQt4VtqItHyEA+Yj8NNZcZzxMB5AoLeVkc+D51A2jBkksiujdUCMNMjCaF8L/BhHGZaaXK5GOk6E4HPIIkeOU6o=
解密后的签名
AB1FAD5119B796DD87FAF8C88D57EF86
判断签名是否一致,校验成功

Macbook MAMP扩展安装指南,pdo_dblib扩展安装,Home-brew安装

Linux下安装pdo_dblib扩展参考我的另一篇文章:https://fores.cc/index.php/archives/21/

由于最近项目需要使用php链接SQL server操作,所以写下php扩展环境安装操作说明
先从Apple Store下载Xcode,然后安装Xcode
接着安装Homebrew包管理,类似于centos下的yum,类似于Ubuntu下的apt-get,后面就可以借助brew安装各种包
终端下输入:


ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
1.安装unixodbc

brew install unixodbc
2.安装freetds,非windows环境访问sql server数据库需要这个证

brew install freetds --with-unixodbc
3.安装php pdo_dblib扩展

brew search pdo-dblib
搜索找到各种php版本的扩展 homebrew/php/php53-pdo-dblib homebrew/php/php56-pdo-dblib homebrew/php/php54-pdo-dblib homebrew/php/php70-pdo-dblib homebrew/php/php55-pdo-dblib homebrew/php/php71-pdo-dblib 我的版本是7.1.5所以我选择安装homebrew/php/php71-pdo-dblib

brew install homebrew/php/php71-pdo-dblib
最后我们可以在终端看到安装的位置在

==> Summary
/usr/local/Cellar/php71-pdo-dblib/7.1.14_20: 7 files, 181KB
4.配置php.ini文件 打开MAMP界面,点php,找到Manually enable other extensions 如果找不到文件,可以通过终端全局搜索,find / -name 'php.ini' 将下面这行加入php.ini配置文件

extension=/usr/local/Cellar/php71-pdo-dblib/7.1.14_20/pdo_dblib.so
5.重启MAMP我们写个phpinfo()函数看下已安装成功

Linux系统下ThinkPHP5链接SQL Server数据库,FreeTDS安装,pdo_dblib扩展安装

linux版本:64位CentOS 6.8

Nginx版本:1.12.0

php版本:7.1.5

Sqlserver版本:2008

1.首先需要编译安装FreeTDS 官网:http://www.freetds.org/software.html
注意根据你SQL Server版本来选择,我的是2008所以填写7.3, --with-tdsver=7.3 参考链接 http://www.freetds.org/userguide/choosingtdsprotocol.htm


    # wget ftp://ftp.freetds.org/pub/freetds/stable/freetds-patched.tar.gz
    # tar -zxvf freetds-patched.tar.gz
    # cd freetds-1.00.83  #解压以后的路径自己看,这个不一定对
    # ./configure --prefix=/usr/local/freetds --with-tdsver=7.3 --enable-msdblib  
    # make && make install


2.验证FreeTDS版本,这一步非常重要,通过才可以继续,不然后面的步骤都是无意义的。
首先看看版本信息


    # /usr/local/freetds/bin/tsql -C


测试数据库是否联通


    # /usr/local/freetds/bin/tsql -H 数据库服务器IP  -p 端口号 -U 用户名 -P 密码  ##端口号一般是1433

3.安装PHP的安装pdo_dblib扩展
http://php.net/downloads.php
上php官网下载对应php版本的源码包找到里面的扩展来安装 我的是7.1.5所以我下载的是7.1的版本
linux下用phpize给PHP动态添加扩展
phpize不同服务器位置可能不一样,你可以通过whereis phpize查找位置,或者 find / -name 'phpize'查询位置
执行./configure 如果你的php不是安装在/usr/local路径下 你要修改为自己的php路径


    #cd php-7.1.15/ext/pdo_dblib
    # /usr/local/php/bin/phpize
    # ./configure --with-php-config=/usr/local/php/bin/php-config --with-pdo-dblib=/usr/local/freetds/
    # make && make install


4.在php.ini配置文件中增加扩展 .so
同上,如果php配置文件不在这里,你可以通过whereis php.ini查找未知,或者 find / -name 'php.ini'查询位置


    #vim /usr/local/php/etc/php.ini
    ##在php配置文件里添加一行
    extension=pdo_dblib.so


5.最后重启php-fpm,可以通过phpinfo()方法查看pdo_dblib扩展是否安装成功


# service php-fpm restart


6.下载附件里面的php类库,配置database.php文件


dblib驱动类库下载:https://fores.cc/usr/uploads/2018/03/1252872861.zip
下载链接2: https://pan.baidu.com/s/1CwYXcRs8F2_hs7lNoaN2Nw 密码: ig3w
下载附件并复制数据库驱动扩展文件到ThinkPHP的文件中
文件放到主程序下 /thinkphp/library/think/db 下方

修改database.php文件里的 type 为 dblib
return [
    // 数据库类型
    'type'            => 'dblib',
    // 服务器地址
    'hostname'        => '',
    // 数据库名
    'database'        => '',
    // 用户名
    'username'        => '',
    // 密码
    'password'        => '',
    // 端口
    'hostport'        => '1433',
    // 连接dsn
    'dsn'             => '',
    // 数据库连接参数
    'params'          => [],
    // 数据库编码默认采用utf8
    'charset'         => 'utf8',
    // 数据库表前缀
    'prefix'          => '',
    // 数据库调试模式
    'debug'           => true,
    // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
    'deploy'          => 0,
    // 数据库读写是否分离 主从式有效
    'rw_separate'     => false,
    // 读写分离后 主服务器数量
    'master_num'      => 1,
    // 指定从服务器序号
    'slave_no'        => '',
    // 是否严格检查字段是否存在
    'fields_strict'   => true,
    // 数据集返回类型
    'resultset_type'  => 'array',
    // 自动写入时间戳字段
    'auto_timestamp'  => false,
    // 时间字段取出后的默认时间格式
    'datetime_format' => 'Y-m-d H:i:s',
    // 是否需要进行SQL性能分析
    'sql_explain'     => false,
];

App Store新规:iOS所有应用将必须适配iPhone X


2018年2月15日,苹果发布公告内容:https://developer.apple.com/news/?id=02152018a

2018年2月16日互联网资讯(详细阅读),苹果官方向开发者发出通知,规定2018年4月开始,所有递交至App Store的新应用,包括通用应用必须使用iOS 11 SDK编译。这意味着,开发者必须使用Xcode 9或更新的版本,且开发者必须保证自己的iOS应用可以完美适配iPhone X的5.8英OLED显示屏。

APICloud平台适配iPhone X教程
由于iPhone X的特殊造型,为了方便开发者对iPhone X进行适配,苹果在iOS 11中引入了Safe Area的概念,引擎也在api对象下添加了safeArea属性和safeareachanged事件,UI设计准则是页面重要的元素需要在安全区域以内,避免被遮挡。

对于大多数应用,通过以下几步基本就可以完成iPhone X的适配,其它的特殊情况如横竖屏切换等则需要结合使用场景另外处理。

注:如果没有iPhone X真机,有需求的开发者可以到这里下载iOS的模块开发工程,使用Xcode9及更高版本将项目运行在iPhone X模拟器上面调试。

一、上传iPhone X启动图

进入控制台端设置,上传iPhone X启动图,图片尺寸为1125*2436,运行效果如下图。若未上传对应的iPhone X启动图或者启动图格式不正确,应用运行在iPhone X上面时上下将有大黑边,不能全屏运行。

二、解决顶部header被遮挡

由于iPhone X顶部的特殊形状,状态栏高度不再是以前的20px,而是变成了44px,如果应用开启了沉浸式效果,那么页面顶部会被遮住部分,如图:

找到api.js中的fixIos7Bar、fixStatusBar方法,用以下代码替换即可。


u.fixIos7Bar = function(el){
    return u.fixStatusBar(el);
};
u.fixStatusBar = function(el){
    if(!u.isElement(el)){
        console.warn('$api.fixStatusBar Function need el param, el param must be DOM Element');
        return 0;
    }
    el.style.paddingTop = api.safeArea.top + 'px';
    return el.offsetHeight;
};
修改过后的顶部效果如图:

三、解决底部标签栏被虚拟home键遮挡 由上面的图可以看到,页面底部的标签栏也被虚拟home键遮挡住了部分。对于虚拟home键,可以通过openWin和setWinAttr方法的hideHomeIndicator参数来控制显示隐藏,这对于沉浸式体验较高的场景很有用(比如观看视频)。而一般的页面通常的做法是避开虚拟home键,这里参考header的处理,我们在api.js中添加一个fixTabBar方法:

u.fixTabBar = function(el){
    if(!u.isElement(el)){
        console.warn('$api.fixTabBar Function need el param, el param must be DOM Element');
        return 0;
    }
    el.style.paddingBottom = api.safeArea.bottom + 'px';
    return el.offsetHeight;
}
然后在需要的地方进行调用:$api.fixTabBar($api.byId('footer')),修改后的效果如图:

关于网站高并发,实现服务器百万级访问稳定运行的解决方案!

-------------挑战和问题-------------

业务多样化的场景,注定了突发业务充满挑战。突发业务具有体量大、场景多样化、 无规律等特点。
a) 体量大:突发业务服务器带宽大部分都超过百兆,部分甚至达到了TB;
b) 场景多样化:公众号推送的新闻爆点;微课堂中的课程直播,才艺等直播;静态网页加速中的红包活动、商城的电商秒杀;学生上下学高峰期自动打卡等;
c) 无规律:部分突发活动无法预知,活动快要开始或已经开始了才知道,比如公众号推送的新闻爆点、圣诞节的一件圣诞帽;
目前存在的问题:

a)大量客户流失:多数用户只有一台服务器运营微擎,客户越多,服务器越卡,导致客户流失。

b)无法降低成本:所有的业务都运行在一台服务器内,CPU满了就只好堆服务器配置,增加了大量成本还是杯水车薪。

-------------解决方案-------------

负载均衡构架如图

WX20180122-164524.png

多台服务器支撑业务系统水平扩展:

我们选用阿里云(或者腾讯云均可,以下以阿里云为例)提供的负载均衡来完成这项工作,较传统技术更简单易用,且能降低60%的成本。负载均衡能够根据应用负载进行弹性扩容,并在流量波动情况下不中断对外服务;负载均衡产品的负载分担能力结合云服务器ECS的快速创建能力,可为我们构建海量用户的系统打下了坚实基础。

通过CDN加速全国用户的静态文件访问:

假如应用的服务器是部署在北京机房,则北京的用户访问是较快的,而广州的用户访问则相对较慢,这是由于广州和北京分别属于不同地区,广州用户访问需要通过互联路由器经过较长的路径才能访问到北京的服务器,返回路径也一样,所以数据传输时间比较长。对于这种情况,可使用 CDN解决,其原理是将数据内容缓存到附近的机房,用户访问时先从最近的机房获取数据,这样可大大减少网络访问的路径,提高用户访问网站的响应速度与网站的可用性,解决网络带宽小、用户访问量大、网点分布不均等问题。

通过缓存加速数据库的访问:

大部分网站访问都遵循28原则,即80%的访问请求,最终落在20%的数据上。因此,我们可以对热点数据进行缓存,减少这些数据的访问路径,减轻对数据库的压力,从而改善系统性,提高用户体验。采用了云Memcached和redis优化,与传统的本地缓存相比,其硬件和数据都部署在云端,有完善的基础设施、网络安全保障、系统维护服务。

通过数据库的分表分库和读写分离,解决容量和性能问题:

随着用户量的增加,数据库会成为最大的瓶颈。改善数据库性能常用的手段是进行读写分离以及分表,读写分离顾名思义就是将数据库分为读库和写库,通过主备功能实现数据同步。

构建海量的文件系统:

随着用户量增加,业务量急剧增加,产生的文件越来越多,这样就会引来存储的容量瓶颈,数据备份,访问性能等一系列问题,单台文件服务器已经不能满足业务需求。远程附件功能提供的海量、安全、低成本,高可靠的分布式存储服务,提供无限存储空间,海量文件的快速访问以及内建的图片处理能力,帮您轻松应对海量文件的存储、访问以及减少带宽。

-------------效果和总结-------------

负载均衡上线后,高效支持了用户的商城秒杀、课程直播、现场大型突发活动,显著提高服务器能力和降低成本。另外微擎工程师根据用户实际情况分析,充分拆分服务器里面运行的业务,放到单独的服务器去运行,将其组合,解决了人数多,突发流量大导致网站崩溃的问题,降低了服务器成本并加速运行访问速度。