学习过小程序的朋友应该知道,在小程序中是不支持cookie的,借助小程序中的缓存我们也可以存储一些信息,但是对于一些比较重要的信息,我们需要通过登录状态维持来保存,同时,为了安全起见,用户的敏感信息,也是需要加密在网络上传输的。

前台,service。封装了http请求,同时封装了getSession(通过code获取服务器生成的session)、getUserInfo(获取用户信息)、getDecryptionData(解密数据)

//service.js
//封装了http服务,getUserInfo,提供回调函数
var recourse = {
doMain: "http://www.domain.com/"
}
module.exports = {
//Http Get
requestGet: function (url, data, cb) {
wx.request({
url: recourse.doMain + url,
data: data,
method: 'GET',
header: {},
success: function (res) {
cb(res, true)
},
fail: function () {
cb(data, false)
}
})
},
//Http POST
requestPost: function (url, data, cb) {
wx.request({
url: recourse.doMain + url,
data: data,
method: 'POST',
header: {},
success: function (res) {
cb(res, true)
},
fail: function () {
cb(data, false)
}
})
},
//获取第三方sessionId
getSession: function (code, cb) {
wx.request({
url: recourse.doMain + 'SmallRoutine/PostCode',
data: { code: code },
method: 'POST',
success: function (res) {
cb(res, true)
},
fail: function (res) {
cb(res, false)
}
})
},
//获取用户信息
getUserInfo: function (cb) {
wx.getUserInfo({
success: function (res) {
cb(res, true)
},
fail: function (res) {
cb(res, false)
}
})
},
//获取解密数据
getDecryptionData: function (cb) {
wx.request({
url: recourse.doMain+'SmallRoutine/Decryption',
data: {
encryptedData: wx.getStorageSync('encryptedData'),
iv: wx.getStorageSync('iv'),
session: wx.getStorageSync('thirdSessionId'),
},
method: 'POST',
success: function (res) {
cb(res, true)
},
fail: function (res) {
cb(res, false)
}
})
}
}

后台,根据code获取session,客户端用来保持登录状态

[HttpPost]
public ActionResult PostCode(string code)
{
try
{
if(!string.IsNullOrEmpty(code))
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(string.Format("https://api.weixin.qq.com/sns/jscode2session?appid={0}&secret={1}&js_code={2}&grant_type=authorization_code",appId,appSecret,code));
request.Method = "GET";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream());
string content = sr.ReadToEnd();
if(response.StatusCode == HttpStatusCode.OK)
{
var successModel = Newtonsoft.Json.JsonConvert.DeserializeObject<ValidateCodeSuccess>(content);
if(null != successModel.session_key)
{
//session_key是微信服务器生成的针对用户数据加密签名的密钥,不应该传输到客户端
var session_key = successModel.session_key;
//3re_session用于服务器和小程序之间做登录状态校验
var thirdSession = Guid.NewGuid().ToString().Replace("-","");
var now = DateTime.Now;
//存到数据库或者redis缓存,这里一小时过期
Service.AddLogin(new Domain.Login()
{
Code = code,
Createime = now,
OpenId = successModel.openid,
OverdueTime = now.AddMinutes(),
SessionKey = successModel.session_key,
SessionRd = thirdSession
});
return Json(new { success = true,session = thirdSession,openId = successModel.openid });
}
else
{
var errModel = Newtonsoft.Json.JsonConvert.DeserializeObject<ValidateCodeFail>(content);
return Json(new { success = false,msg = errModel.errcode + ":" + errModel.errmsg });
}
}
else
{
var errModel = Newtonsoft.Json.JsonConvert.DeserializeObject<ValidateCodeFail>(content);
return Json(new { success = false,msg = errModel.errcode + ":" + errModel.errmsg });
}
}
else
{
return Json(new { success = false,msg = "code不能为null" });
}
}
catch(Exception e)
{
return Json(new { success = false });
}
}

解密敏感信息

[HttpPost]
public ActionResult Decryption(string encryptedData,string iv,string session)
{
try
{
var sessionKey = Service.GetSessionKey(session);
if(!string.IsNullOrEmpty(sessionKey))
{
var str = AESDecrypt(encryptedData,sessionKey,iv);
var data = Newtonsoft.Json.JsonConvert.DeserializeObject<EncryptedData>(str);
if(null != data)
{
//服务器可以更新用户信息
return Json(new { success = true,data = data });
}
}
}
catch(Exception e)
{
Service.AddLog("翻译错误:"+e.ToString());
}
return Json(new { success = false });
}

AES解密

public static string AESDecrypt(string encryptedData,string key,string iv)
{
if(string.IsNullOrEmpty(encryptedData)) return "";
byte[] encryptedData2 = Convert.FromBase64String(encryptedData);
System.Security.Cryptography.RijndaelManaged rm = new System.Security.Cryptography.RijndaelManaged
{
Key = Convert.FromBase64String(key),
IV = Convert.FromBase64String(iv),
Mode = System.Security.Cryptography.CipherMode.CBC,
Padding = System.Security.Cryptography.PaddingMode.PKCS7
};
System.Security.Cryptography.ICryptoTransform ctf = rm.CreateDecryptor();
Byte[] resultArray = ctf.TransformFinalBlock(encryptedData2,,encryptedData2.Length);
return Encoding.UTF8.GetString(resultArray);
}

判断用户是否掉线

[HttpPost]
public ActionResult PostSession(string session)
{
if(!string.IsNullOrEmpty(session))
{
var loginInfo = Service.GetLoginInfo(session);
if(null != loginInfo)
{
return Json(new { success = true,openId = loginInfo.OpenId });
}
else
{
return Json(new { success = false });
}
}
return Json(new { success = false });
}

前台index.js

//index.js
var app = getApp()
Page({
data: {
userInfo: {},
},
onLoad: function () {
var that = this
app.getUserInfo(function (userInfo) {
//更新数据
that.setData({
userInfo: userInfo
})
})
}
})

前台app.js

var service = require('./service/service.js')
var appConfig = {
getUserInfo: function (cb) {
var that = this
if (that.globalData.userInfo) {
//从缓存中用户信息
} else {
//wx api 登录
wx.login({
success: function (res) {
console.log('登录成功 code 为:' + res.code);
if (res.code) {
service.getSession(res.code, function (res, success) {
if (success) {
console.log('通过 code 获取第三方服务器 session 成功, session 为:' + res.data.session);
//缓存起来
wx.setStorageSync('thirdSessionId', res.data.session);
//wx api 获取用户信息
service.getUserInfo(function (res, success) {
if (success) {
console.log('获取用户信息成功, 加密数据为:' + res.encryptedData);
console.log('获取用户信息成功, 加密向量为:' + res.iv);
//缓存敏感的用户信息,解密向量
wx.setStorageSync('encryptedData', res.encryptedData);
wx.setStorageSync('iv', res.iv);
that.globalData.userInfo = res.userInfo;
//解密数据
service.getDecryptionData(function (res, success) {
if (success) {
console.log("解密数据成功");
console.log(res.data.data);
} else {
console.log('解密数据失败');
}
})
} else {
console.log('获取用户信息失败')
}
});
} else {
console.log('通过 code 获取第三方服务器 session 失败');
}
});
} else {
console.log('登录失败:');
}
}
})
}
},
globalData: {
userInfo: null
}
}
App(appConfig) 

运行输出

微信小程序登录数据解密以及状态维持的更多相关文章

  1. [转]微信小程序登录数据解密以及状态维持

    本文转自:http://www.cnblogs.com/cheesebar/p/6689326.html 学习过小程序的朋友应该知道,在小程序中是不支持cookie的,借助小程序中的缓存我们也可以存储 ...

  2. 微信小程序开放数据解密 AES-128-CBC 解密(C#版本)

    最近在开发小程序,需要跟微信服务端交互,微信敏感数据都有加密返回,需要在服务端接收进行解密后再返回给客户端小程序,今天就通过C# 进行数据的解密,官方下载下来是Node.C++.php等,就是没有C# ...

  3. 微信小程序用户数据解密

    概述 通过微信web开发者工具创建登录,获取用户信息,发送至后台,进行用户数据解密 详细 代码下载:http://www.demodashi.com/demo/10705.html 一.准备工作 1. ...

  4. laravel 微信小程序登录 加密解密扩展包

    https://github.com/lanceWan/wxxcx 测试的时候一定要保证服务器的 appid  和客户端的appid一致 如果是切换测试 那么需要把本地的项目从微信小程序上面删除掉 再 ...

  5. 基于Shiro,JWT实现微信小程序登录完整例子

    小程序官方流程图如下,官方地址 : https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html ...

  6. Flask与微信小程序登录(后端)

    开发微信小程序时,接入小程序的授权登录可以快速实现用户注册登录的步骤,是快速建立用户体系的重要一步.这篇文章将介绍 python + flask + 微信小程序实现用户快速注册登录方案(本文主要进行后 ...

  7. 微信小程序登录方案

    微信小程序登录方案 登录程序 app.js 调用wx.login获取code 将code作为参数请求自己业务登录接口获取session_key 存储session_key 如果有回调执行回调 App( ...

  8. 微信小程序登录,获取code,获取openid,获取session_key

    微信小程序登录 wx.login(Object object) 调用接口获取登录凭证(code).通过凭证进而换取用户登录态信息,包括用户的唯一标识(openid)及本次登录的会话密钥(session ...

  9. 微信小程序登录对接Django后端实现JWT方式验证登录

    先上效果图 点击授权按钮后可以显示部分资料和头像,点击修改资料可以修改部分资料. 流程 1.使用微信小程序登录和获取用户信息Api接口 2.把Api获取的用户资料和code发送给django后端 3. ...

随机推荐

  1. 2017-2-24 C#基础 for循环的嵌套

    用几个练习题演示一下for循环的嵌套 1.打印以下图形 ★★★★★★★★★★★★★★★ namespace _2017_2_24_for循环的嵌套 { class Program { static v ...

  2. 深入理解Node系列-细说Connect(上)

    前言 想必对于广大前后端的同学们,Node 或是用来作为网站服务器的搭建,亦或是用来作为开发脚手架的运用,或是早有套路,亦或是浅尝辄止.从现在开始博主将会不定时的对 Node 系列的产品做分析,其中夹 ...

  3. perl 之eval

    eval是个表达式,语句末尾有一个分号, 发现在它的监视范围内出现致命错误,会立即停止运行整个块,退出后继续运行其 余的代码   eval的返回值就是语句块最后一条表达式的执行结果   eval非正常 ...

  4. ERP库位分布看板(库位管理)

    客户正在使用的看板管理,根据厂家需求,做的二次开发. 一:看板效果 二:客户需求 1.客户需求:XX是一家汽车零部件(胶管,硅胶管等)的生产厂家,因此对原料,半成品的有效期有严格的要求. 多次调研得知 ...

  5. 写lua时需要注意的地方

    条件语句判断时,只有false和nil会导致判断为假,其他的任何值都为真. Lua 的字符串与编码无关: 它不关心字符串中具体内容. 标准 Lua 使用 64 位整数和双精度(64 位)浮点数, 但你 ...

  6. 【2017-2-17】VS基本应用及C#基础第一节(定义变量、输入及输出)

    一VS基本应用 (一)新建项目 新建项目可有多种方法例如: 1.  在VS起始页面建立新项目 2.  在集成环境中,通过"文件"/"新建"/"项目&q ...

  7. 从覆盖bootstrap样式谈css选择器优先级

    样式优先级 首先简单说几个定义样式的方式: 元素内嵌: <li><a href="" style="color:#ffffff;">SH ...

  8. 棋盘覆盖(一) ACM

    棋盘覆盖 描述 在一个2k×2k(1<=k<=100)的棋盘中恰有一方格被覆盖,如图1(k=2时),现用一缺角的2×2方格(图2为其中缺右下角的一个),去覆盖2k×2k未被覆盖过的方格,求 ...

  9. Eclipse 项目导入 Studio Debug运行卡死在进入界面

    最近,把一个以前开发的Eclipse的项目导入Studio中,遇到了各种奇葩的问题,这时候就要参考百度了,基本都能解决,我导入的项目遇到的问题在百度中都能找到答案,那么我这里就不在做总结了 第二天,发 ...

  10. ORM-Dapper学习<一>

    ORM 框架简介 对象-关系映射(Object/Relation Mapping,简称ORM),是随着面向对象的软件开发方法发展而产生的.面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,关 ...