前言
前端小白,打算边学边写学习笔记,强化理解。若有不合理之处,也请大佬们帮忙指出,非常感谢!若有幸帮到他人,大家有缘,也非常开心~
关于本文内容,是在开发百度小程序中的用户登录系统时遇到的。作为初学者,有必要总结一下。
在开始正文之前,先了解一下什么是openid和session_key?
openid:用户唯一标识。百度注册用户在访问小程序时,会产生一个用户唯一的OpenID(针对该小程序)。用户openid的生成原理是,用户的百度账号再加上开发者的小程序client_id经过某种加密算法得到的。
session_key:与服务器的会话密钥。
1、利用原生API获取用户的openid和session_key
利用原生API获取用户的openid和session_key本身不难,只要找到百度小程序开发文档里的相关内容就成功一大半了。有点前端基础的同学应该都能看懂文档中的内容,并参照内容里给的案例进行开发,得到自己想要的opened和session_key。
文档地址:smartprogram.baidu.com/docs/develo…
示例代码
在js文件中:
Page({
data: {
sessionKey: ''
},
getSessionKey() {
swan.login({
success: res => {
swan.request({
url: 'https://spapi.baidu.com/oauth/jscode2sessionkey',
method: 'POST',
header: {
'content-type': 'application/x-www-form-urlencoded'
},
data: {
// swan.login()返回的 code
code: res.code,
client_id: 'xxxxxxxxxxxxxxxxxx',
sk: 'xxxxxxxxxxxxxxxxxxxxxxx'
},
success: res => {
if (res.statusCode === 200) {
this.setData({
sessionKey: res.data.session_key || ''
});
}
}
});
}
});
}
});
在 swan 文件中
<view class="intro">
<button type="primary" bind:tap="getSessionKey">获取 session key</button>
</view>
<view class="container" s-if="{{sessionKey}}">
<view>session key 值为:</view>
{{sessionKey}}
</view>
res.data 的值为
# curl -d "code=xxx&client_id=xxx&sk=xxx"
https://spapi.baidu.com/oauth/jscode2sessionkey
{
"openid": "ABCDEFG123",
"session_key": "xxxxxx"
}
注意点
上文示例代码的js文件中,swan.request()方法里data用到的三个数据。其中code必须是调用swan.login()方法success后返回的res.code,而client_id和sk必须分别是小程序自己的AppKey和AppSecret,否则返回不到正确的openid。
2、包装用于获得openid和session_key的api接口https://spapi.baidu.com/oauth/jscode2sessionkey
为什么要包装该接口?
- 在上文示例代码中,我们可以看到,使用该接口需要用到小程序的AppKey和AppSecret,而AppSecret是一个非常重要的字段,使用该密码可以调用小程序的所有后台接口。所以不能把该字段放到小程序的前端代码中,因为百度手机客户端容易被反编译并轻松获得Appsecret,造成重大安全威胁。因此我们需要把Appsecret保存到后台服务器中,通过服务器使用Appsecret获取openid和session_key。
这个说明为了安全性着想。我们不能在前端通过上文的原生接口读取用户的openid。必须把它们放在后端处理,然后通过接口的形式返回给前端。
如何做?
我用的是node.js写的后端。使用express框架,以及request模块来发起url请求
var express = require('express');
var app = express();
var request = require('request')
var URL = require('url');
app.use('/Users/xxxxxxx', express.static('/Users/xxxxxxx'));
app.get('/', function (req, res) {
res.send('hello world');
})
app.get('/swanapp_jscode2session', function (req, res) {
var client_id = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx'; // 换成自己的AppKey
var sk = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx'; // 换成自己的AppSecret
var params = URL.parse(req.url, true).query;;
var url = 'https://spapi.baidu.com/oauth/jscode2sessionkey?code='+params.code+'&client_id='+client_id+'&sk='+sk;
request(url, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body)
}
res.send(body);
})
})
var server = app.listen(8081,function () {
var host = server.address().address
var port = server.address().port
console.log("应用实例,访问地址为 http://www.localhost.com:%s")
})
前端读取getopenid接口
Page({
data: {
sessionKey: ''
},
getSessionKey() {
swan.login({
success: res => {
if(!!res.code){
swan.request({
url: 'http://www.localhost.com:8081/swanapp_jscode2session?code='+res.code,
method: 'GET',
header: {
'content-type': 'application/x-www-form-urlencoded'
},
success: res => {
console.log(res)
if (res.statusCode === 200) {
this.setData({
openid: res.data.openid,
sessionKey: res.data.session_key || ''
});
}
}
});
}
}
});
}
});
这样就能安全读取用户的openid和session_key了。
记住不要把自己小程序的appkey和appsecret放在前端代码中。