多端开发,听名字就感觉不一样,一套代码,多端使用。适用于各个平台。是不是很高大上。
市面上很多关于多端开发的框架,比较常用,流行的框架 uni-app,Chameleon(变色龙),taro这些,都可以支持多端,一套代码,8个平台支持
常见平台分别是H5页面,安卓,微信小程序,百度小程序,支付宝小程序,头条小程序这几个平台
下面以一个登陆的例子给大家介绍一下
一、创建项目、后端环境介绍
- 创建项目
- 打开HBuilderX -> 新建 uniapp 项目;
- 创建页面
|_ index.vue 入口页面
|_ write.vue 文章撰写页面
|_ my.vue 账户中心页面
- 后端使用php+mysql
完善底部导航栏
- 下载图标, 图标地址 :
https://pan.baidu.com/s/1iaWd6l_-cIJ3RNUsqNqFNQ - 将图标部署至 /static 目录;
- 修改 page.json
“color” : “#707070”,
“selectedColor” : “#DE533A”,
“list” : [
{
“pagePath” : “pages/index/index”,
“text” : “文章”,
“iconPath” : “static/nav1.png”,
“selectedIconPath” : “static/nav1-a.png”
},
{
“pagePath” : “pages/write/write”,
“text” : “写作”,
“iconPath” : “static/nav2.png”,
“selectedIconPath” : “static/nav2-a.png”
},
{
“pagePath” : “pages/my/my”,
“text” : “我的”,
“iconPath” : “static/nav3.png”,
“selectedIconPath” : “static/nav3-a.png”
}
]
}
“navigationBarTextStyle” : “black”,
“navigationBarTitleText” : “悦读”,
“navigationBarBackgroundColor” : “#F8F8F8”,
“backgroundColor” : “#F8F8F8”
}
https://github.com/weilanwl/ColorUI
二、封装全局登录检查函数并部署
var SUID = uni.getStorageSync(‘SUID’);
var SRAND = uni.getStorageSync(‘SRAND’);
var SNAME = uni.getStorageSync(‘SNAME’);
var SFACE = uni.getStorageSync(‘SFACE’);
if(SUID == ” || SRAND == ” || SFACE == ”){
uni.redirectTo({url:’../login/login?backpage=’+backpage+’&backtype=’+backtype});
return false;
}
return [SUID, SRAND, SNAME, SFACE];
}
backpage, backtype 2个参数分别代表:
backpage : 登录后返回的页面
backtype : 打开页面的类型[1 : redirectTo 2 : switchTab]
返回值说明
已经登录返回数组 [用户 id, 用户随机码, 用户昵称, 用户表情]
login 页面作为登录过度页面,多端登录都通过此页面完成!
export default {
data() {
return {
};
},
onLoad : function() {
var loginRes = this.checkLogin(‘../my/my’, ‘2’);
if(!loginRes){return false;}
}
}
</script>
三、UNI-APP端使用微信登录原理和条件编译
export default {
data() {
return {
};
},
onLoad:function(){
//app 端微信登录
// 手册位置 https://uniapp.dcloud.io/api/plugins/login?id=getuserinfo
// #ifdef APP-PLUS
uni.login({
success: (res) => {
// res 对象格式
//{“code”:”***”,
//”authResult”:{
//”openid”:”***”,
//”scope”:”snsapi_userinfo”,
//”refresh_token”:”**”,
//”code”:”****”,
//”unionid”:”***”,
//”access_token”:”***”,
//”expires_in”:7200
//},
//”errMsg”:”login:ok”}
uni.getUserInfo({
success: (info) => {
// info 对象格式
// {“errMsg”:”getUserInfo:ok”,
// “rawData”:”…
// “userInfo”:{
//”openId”:”***”,
//”nickName”:”***”,
//”gender”:1,
// “city”:”Xi’an”,
// “province”:”Shaanxi”,
// “country”:”China”,
// “avatarUrl”:”头像”,
// “unionId”:”oU5Yyt_agt547zWyA0v0eLfFPqxo”
//},”signature”:””}
// 与服务器交互将数据提交到服务端数据库
},
fail: () => {
uni.showToast({title:”微信登录授权失败”});
}
})
},
fail: () => {
uni.showToast({title:”微信登录授权失败”});
}
})
// #endif
}
}
</script>
四、多平台多应用 统一登录微信关系
只要是同一个微信开放平台帐号下的公众号,用户的UnionID是唯一的。
此前的OpenID机制,每个微信号对应每个应用有唯一的OpenID,所以不同应用之间是不能共享用户的,现在有了UnionID就可以了。
使用 uni.login 即可;
2、使用 uni.login 登录时会获取 code,用 code 换取 seesion_key;
3、在获取用户信息函数中获取到加密信息;
4、利用 seesion_key 及加密信息在服务端解密获取 unionID
data() {
return {
};
},
methods:{
// #ifdef MP-WEIXIN
getUserInfo : (info) => {
//加密数据
var encryptedData = info.mp.detail.encryptedData;
var iv = info.mp.detail.iv;
info = info.mp.detail.userInfo;
//info
//userInfo {“nickName”:”深海”,”gender”:1,…avatarUrl”:”https://7tdPvkPaJlkaLFFbLAffGVApluZdanLkDVplNlAhq1EJA/132″}
//与服务器交互进行解密
uni.request({
url: _self.apiServer+’member&m=wxaes’,
method: ‘POST’,
header: {‘content-type’ : “application/x-www-form-urlencoded”},
data: {
session_key : session_key,
encryptedData : encryptedData,
iv : iv
},
success: res => {
console.log(res);
//此处可以成功获取 unionId 利用 unionId 完成登录即可
},
fail: () => {},
complete: () => {}
});
}
},
onLoad:function(options){
_self = this;
pageOptions = options;
// #ifdef MP-WEIXIN
// 调用 微信 login 获取 code
uni.login({
success: (res) => {
uni.request({
url:_self.apiServer+’member&m=codeToSession&code=’+res.code,
success: (sessions) => {
session_key = sessions.data.session_key;
}
}
}
});
}
});
// #endif
}
namespace hsC;
class member{
//……
public function wxaes(){
if(empty($_POST[‘session_key’]) || empty($_POST[‘encryptedData’]) || empty($_POST[‘iv’])){exit(jsonCode(‘error’, ‘data error’));}
include HS_TOOLS.’WXBizDataCrypt.php’;
$pc = new \WXBizDataCrypt(HS_APPID, $_POST[‘session_key’]);
$data = ”;
$errCode = $pc->decryptData($_POST[‘encryptedData’], $_POST[‘iv’], $data);
if ($errCode == 0) {
exit($data);
} else {
exit(jsonCode(‘error’, $errCode));
}
}
}
五、api接口安全策略 – 签名策略
前面章节讲解的接口是裸露的、不安全的!使用post、get模拟可以轻松对api进行请求,最简单的攻击就可以瞬间完成近万会员的注册!
所以在进行api接口通讯的同时我们应该进行数据的验证工作!
2、前端对accessToken进行随机性拆分及md5加密,产生签名(保存在本地存储中);
3、前端在与后端进行交互时传递签名;
4、后端接收数据是验证签名;
1.2 sign.js // 签名函数
module.exports = {
sign : function(apiServer){
// 环境判断非uni环境不支持
if(!uni){return ‘…’;}
// 连接服务器获取一个临时的accessToken
uni.request({
url: apiServer+’getAccessToken’,
method: ‘GET’,
success: res => {
if(res.data.status != ‘ok’){return ;}
var data = res.data.data;
// 对 accessToken 进行md5加密
var accessToken = md5.hex_md5(data.token + data.time);
// 签名 = md5(accessToekn + time) + ‘-‘ + ‘accessToekn’;
var sign = accessToken + ‘-‘ + data.token;
//console.log(sign);
// 记录在本地
uni.setStorage({
key:”sign”,
data:sign
});
}
});
}
}
CREATE TABLE `yuedu_access_tokens` (
`token` varchar(30) NOT NULL,
`time` int(11) DEFAULT NULL,
PRIMARY KEY (`token`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
//getAccessToken.php
namespace hsC;
class getAccessToken{
public function index(){
$db = \hsTool\db::getInstance(‘access_tokens’);
$token = array(
‘token’ => uniqid(),
‘time’ => time()
);
$db->add($token);
exit(jsonCode(‘ok’, $token));
}
}
在数据提交页面提交之前进行预签名,提交数据时携带此签名!
因为大家后端基础不一样,本课程使用数据库保存了accessToken,更好的方式是 redis 或 memcache,可以设置变量有效期并能自动失效!
微信赞赏支付宝扫码领红包