参考:
微信正式文件*小程序登录过程
微信正式文件*小程序
本文参考了以上文档,加上我自己的理解和整合。
登录过程前端调用wx.login()获取临时登录证书代码,并将其发送回开发人员服务器。后端调用auth.code2Session接口,以换取用户的唯一标识OpenID和会话密钥session_key。开发人员服务器可以根据用户标识生成自定义登录状态,该状态用于在后续业务逻辑中的前端和后端交互期间标识用户的身份。
上图是小程序登录的基本过程。
作为后端开发人员,在阅读了上面的描述之后,我的心是这样的:
好吧,我知道事实,如何编写代码?
接下来,我们使用go来实现此过程:
首先,代码是从前端获取并传输到后端的,我们不在乎,只要我们在HTTP请求中获得此参数即可。
好的,已经获得了第一步的代码。
然后第二步,使用代码获取openID和session_key,这里我们看一下微信官方文档给出的界面:
这里有一个界面。使用返回值,我们可以通过HTTP请求获取openID和session_key。
现在我开始编写代码实现,我使用go语言,但事实是一样的。
定义返回值数据结构:
type WXLoginResp struct {OpenId string`json:"openid"`SessionKey string`json:"session_key"`UnionId string`json:"unionid"`ErrCode int`json:"errcode"`ErrMsg string`json:"errmsg"`}
定义实现功能:
// 这个函数以 code 作为输入, 返回调用微信接口得到的对象指针和异常情况func WXLogin(code string) (*WXLoginResp, error) {url := "https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code"// 合成url, 这里的appId和secret是在微信公众平台上获取的url = fmt.Sprintf(url, appId, secret, code) // 创建http get请求resp,err := http.Get(url)if err != nil {return nil, err}defer resp.Body.Close()// 解析http请求中body 数据到我们定义的结构体中wxResp := WXLoginResp{}decoder := json.NewDecoder(resp.Body)if err := decoder.Decode(&wxResp); err != nil {return nil, err}// 判断微信接口返回的是否是一个异常情况if wxResp.ErrCode != 0 {return nil, errors.New(fmt.Sprintf("ErrCode:%s ErrMsg:%s", wxResp.ErrCode, wxResp.ErrMsg))}return &wxResp, nil}
好的,在这里,我们已经获得了openid和session_key。
下一步,执行第三步,此步骤更加灵活,根据您自己的需求生成自定义登录状态,并返回到前端;
这里我们使用gin框架实现路由接口,将上述内容串联起来形成一个完整的过程;以下代码仅供参考
// /wechat/applet_login?code=xxx [get] 路由// 微信小程序|微信小程序登录func AppletWeChatLogin(c *gin.Context) {code := c.Query("code") // 获取code// 根据code获取 openID 和 session_keywxLoginResp,err := models.WXLogin(code)if err != nil {c.JSON(400, util.Fail(err.Error()))return}// 保存登录态session := sessions.Default(c)session.Set("openid", wxLoginResp.OpenId)session.Set("sessionKey", wxLoginResp.SessionKey )// 这里用openid和sessionkey的串接 进行MD5之后作为该用户的自定义登录态mySession := GetMD5Encode(wxLoginResp.OpenId + wxLoginResp.SessionKey)// 接下来可以将openid 和 sessionkey, mySession 存储到数据库中, // 但这里要保证mySession 唯一, 以便于用mySession去索引openid 和sessionkeyc.String(200, mySession)}// 将一个字符串进行MD5加密后返回加密后的字符串func GetMD5Encode(data string) string {h := md5.New()h.Write([]byte(data))return hex.EncodeToString(h.Sum(nil))}
也许代码部分不容易理解,下面是一段文字说明:
获取路线中的code参数。使用代码来调用我们之前编写的函数以获取openid和session_key。使用获得的openid和session_key生成我们的自定义登录状态(有很多方法,只需确保生成的值是全局唯一的即可。在这里,我们进行了简化,将openid和session_key直接用于MD5加密,并将获得的字符串用作我们的登录名状态(这里的登录状态可以理解为一个索引,本质上是一个字符串))最后,我们定义的登录状态以及openid和session_key存储在数据库中,并确保用户的openid和session_key可以以自定义登录状态唯一查询。这样我们以后就可以查询它们。
微信小程序登录已基本完成。
这里微信正式提供了一个验证界面,以验证小程序获得的用户信息是否完整。这也是我们之前获得的session_key的含义,
在这里您可以参考:微信正式文件*背景验证和解密数据
我们还提供了非常简单的验证码:
实际上,它是前端提供的微信原始数据和我们之前获得的session_key的MD5加密,并且获得了signature2,并将其与微信加密的结果进行比较,这意味着存在没有变化,并且差异意味着原始数据出现了。已更改。
// 校验微信返回的用户数据func validateUserInfo(rawData, sessionKey, signature string) bool {signature2 := GetSha1(rawData + sessionKey)return signature == signature2}// SHA-1 加密func GetSha1(str string) string {data := []byte(str)has := sha1.Sum(data)res := fmt.Sprintf("%x", has) //将[]byte转成16进制return res}

