微信小程序 “万利商城”实战之五: 用户身份认证原理及详细编码实现(1)

一个商城系统必定涉及到用户身份识别的问题,用户进入小程序后用什么来标记他的身份?

对于一个web应用来说, 典型的设计是这样的 :

用户打开注册页面-->填写“账号、密码等基本信息”-->点击“注册” , 然后,

系统将这些信息存储到数据库中,同时在web服务器上生成一个session , response会将带有cookie信息的报文发送给浏览器,

用户再次访问页面的时候浏览器会带着这个cookie 信息给web服务器,服务器解析这个 cookie并和session关联起来,

从而完成对用户的身份识别 。

 

在小程序中是否有类似的方式来识别用户 ? 再回答这个问题前,先看看官方文档是如何描述的 :

官方连接 : https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html

---------------------------------------------------------------------分割线-----------------------------------------------------------------------

小程序登录

小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。

说明:

    调用 wx.login() 获取 临时登录凭证code ,并回传到开发者服务器。
    调用 auth.code2Session 接口,换取 用户唯一标识 OpenID 和 会话密钥 session_key。
之后开发者服务器可以根据用户标识来生成自定义登录态,用于后续业务逻辑中前后端交互时识别用户身份。

注意:

    会话密钥 session_key 是对用户数据进行 加密签名 的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥。
    临时登录凭证 code 只能使用一次

----------------------------------------------------分割线------------------------------------------------------------

从上可以看出小程序用户的身份标识就是  openid ,得到这个openid ,就可以唯一标识一个微信用户 ,也就是说,

用户进入不同小程序时openid不同,但同一个小程序中,不管在什么情况下进入,openid 都是固定且唯一的。

接下来我们看看如何编码实现这个身份认证系统 。

第一步 ,数据库设计(users表) :

字段 user_id(int) openid(varchar(50)) session_key(varchar(50)) signin_time(datetime) user_token(char(36))  
说明 用户编号,自增 微信openid 微信session_key 登录时间  guid字符串  

  说明 :微信官方文档并未有说明openid和session_key的字符长度 , 目前是28~36位 , 为保险起见,将此字段尽量放长一点。

第二步 ,Web页面设计 :

  1 . 用户登录的URL : http://localhost/web/user/signin ,伪代码如下:

 1             //访问微信接口服务
 2             string code = context.Request.QueryString["code"];
 3             string url = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code"
 4             WebRequest request = WebRequest.Create(url);
 5             request.Method = "GET";
 6             WebResponse response = request.GetResponse();
 7             Stream stream = response.GetResponseStream();
 8             StreamReader reader = new StreamReader(stream, Encoding.UTF8);
 9             string content = reader.ReadToEnd();//读取微信接口返回的用户信息
10             reader.Close();
11             stream.Close();
12              
13             //用第三方库解析微信接口返回的用户信息
14             RootObject ro = JsonConvert.DeserializeObject<RootObject>(content);//Newtonsoft.Json
15             string openid = ro.openid;
16             string session_key = ro.session_key;
17             string signin_time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
18             string user_token = Guid.NewGuid().ToString();
19        //查找用户是否存在数据库中
20             string sql = "select * from users where openid=?";
21             MySqlCommand cmd = new MySqlCommand(sql, conn);//MySql.Data
22             cmd.Parameters.AddWithValue("openid", openid);
23             conn.Open();
24             MySqlDataReader reader = cmd.ExecuteReader();
25             if (!reader.Read())
26             { 
27                 //不存在就插入到数据库
28                 sql = "INSERT INTO users(openid,session_key,signin_time,user_token) VALUES(?,?,?,?)";
29                 cmd.CommandText = sql;
30                 cmd.Parameters.Clear();
31                 cmd.Parameters.AddWithValue("openid", openid);
32                 cmd.Parameters.AddWithValue("session_key", session_key);
33                 cmd.Parameters.AddWithValue("signin_time", signin_time);
34                 cmd.Parameters.AddWithValue("user_token", user_token);
35                 cmd.ExecuteNonQuery();
36             }
37             reader.Close();
38             conn.Close();
39 
40             //数据库查询用户信息并返回给小程序端,代码省略。
41             context.Response.Write("{'userid':111,'usertoken':'234aaa-34234-3423-423423-asd'}");

 第三步 , 小程序端设计 :

  1 . 打开app.js这个文件 , 删除所有 onLaunch: function () { }这个函数中的内容,添加如下的代码 :

 1 onLaunch: function () {
 2         var _this = this;
 3         var userinfo = wx.getStorageSync('userinfo');
 4         if (!userinfo){
 5             wx.login({
 6                 success: function (res) {
 7                     console.log(res.code);
 8                     wx.request({
 9                         data:{
10                             "code":res.code   
11                         },
12                         method:"GET",
13                         url: 'http://localhost/web/user/add',
14                         success: function (res) {
15                             if(res.statusCode==200){
16                                 wx.setStorageSync('userinfo', res.data);//将用户信息保存到本地供后续的页面来使用
17                             }
18                             console.log(res.state);
19                         }
20                     })
21                 },
22             });
23         }
24     },

剖析一下上面的代码 :

用户进入小程序时会自动执行onLaunch函数 ,wx.getStorageSync('userinfo');用于获取本地存储中的用户信息,

如果没有(第一次进入或本地存储被微信回收后都为空)  ,用 wx.login()拿到code后通过 wx.request() 传递到Web服务器上 ,

Web服务器用这个code做参数去访问微信接口服务:

GET https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code

微信接口服务将返回如下JSON数据包 :

正常情况下, 我们就可以获取到openid和session_key了。

 

Web服务器获取到openid和session_key后需要用openid做条件查询users表, 如果没有查询到用户数据 , 说明此用户是第一进入小程序,

所以要插入一条数据到users表, 其中signin_time是当前时间 , user_token是随机生成的guid类型的字符串,插入完成后,

将用户信息拼装成JSON字符串后Response.Write()给小程序, 如果查询到用户数据,则直接将用户信息拼装成JSON字符串后Response.Write()给小程序。

小程序用wx.setStorageSync('userinfo', res.data);将用户信息保存到本地供后续的页面来使用用户信息。

至此, 我们就完成了用户的登录动作。

 

posted @ 2020-10-30 01:45  屏风马  阅读(650)  评论(0编辑  收藏  举报