踩过微信小程序坑的人都知道,微信小程序是不支持cookie的。微信小程序采用的是wx.login获取code,经过开发者服务器端同微信服务器进行数据交互实现登陆。获得openid或者unionid与本地数据库关联,从而获得登陆用户相关信息。html
具体参考微信相关文档wx.login,这里不赘述。前端
一般状况下,咱们不单单是须要用户数据,还须要用户的登陆状态,也就是session和cookie机制。要命的是小程序不支持cookie,没有了cookie,session也无从谈起。这里基于node.js的express和koa,经过header头添加标记的方式,模拟cookie,从而在服务器端引入session。node
cookie的本质是惟一字符串标记,由浏览器自动生成(这里是做为会话方案,而非数据存储方案而言)。既然是惟一字符串标记,那咱们也能够本身生成一个相似的标记,添加到Headers头中,相似这样git
let header={'x-xxxx-cookie':'uuid cookie'}; // wx.request({ url:url, data:data, header:header, method:method, success: function( res ) { }, fail: function( error ) { } });
须要注意的是,这里的uuid cookie最好使用服务器端的session ID,后面再说为何?github
以上就是前端(小程序端)的处理,接下来是服务器端的处理,服务器端使用的是express或者koa,具体使用请移步:
Express
Koaredis
服务器端Express中session使用的是express-session,Koa中使用的是koa-generic-session,对于Koa这里多说一句,本来也打算使用koa-session,最后放弃选择了前者,由于后者没有暴露出相似获取session ID的参数,而整个过程当中须要获取到session ID很是重要。session存储都使用Redis。
Express部分代码以下:数据库
var express = require('express'); var session = require('express-session'); var cookieParser = require('cookie-parser'); var RedisStore = require('connect-redis')(session); // var sessionStore=new RedisStore({ host:config.redis.host, port:config.redis.port }); var app = express(); // app.use(cookieParser()); //cookie var cookieParser=cookieParser(config.secret); app.use(cookieParser); //session var sessionParser = session({ store:sessionStore, secret:config.secret, }); app.use(sessionParser); //
Koa部分代码:express
const Koa = require('koa'); const session = require('koa-generic-session'); //const session = require('koa-session'); const RedisStore = require('koa-redis'); // const app = new Koa(); // middlewares app.use(bodyparser({ enableTypes:['json', 'form', 'text'] })); // let sessionStore=new RedisStore(sessionRedisOptions); let sessionOptions={ store: sessionStore, key: '', }; // const sessionParser = session(sessionOptions,app); app.use(sessionParser);
获取session ID,Express中能够直接经过req.sessionID获取获得,koa中使用ctx.sessionId获取获得。之因此session ID重要,主要是咱们能够直接经过它获取到session。若是不使用session ID的方式的话,咱们须要本身额外去存储相关数据,能够不用将数据挂载到req.session或者ctx.session上,会带来额外的代码成本。并且万一哪天微信小程序支持cookie了呢,采用session ID方式,仍是和之前同样操做session数据。json
咱们须要将session ID从服务器端返回到小程序端,一般会在第一个请求的时候就返回,而后小程序端将该数据保存,相似这样:小程序
app.globalData.cookieID=uuid cookie;//uuid cookie为服务器端返回的session ID
小程序端之后的请求都将该数据添加到Headers头中传递到服务器端。
服务器端下一个请求,直接经过req.session或者ctx.session仍是获取不到以前设置的session数据啊!
的确是的,咱们须要在路由以前,添加一个中间件来解决。相似这样:
Express部分代码:
app.use(function(req,res,next){ // var sessionID=req.headers['x-xxxx-cookie']; if(sessionID){ // return sessionStore.get(sessionID,function(err,session){ // req.session=Object.assign(req.session||{},session||{}); // next(); }); } // next(); });
Koa部分代码:
app.use(async function (ctx,next){ // var cookies=ctx.cookies; var sessionID=ctx.request.headers['x-xxxx-cookie']||cookies.get(sessionOptions.key); if(sessionID){ // let sess= await ctx.sessionStore.get(sessionID); // let session=Object.assign(ctx.session||{},sess||{}); ctx.session=session; } // await next(); });
也就是咱们须要经过session ID获得session,而后赋值到req.session或者ctx.session上,保证以后能够直接按照普通方式操做session数据。
好了,就到这里,总结一下:
经过header添加类cookie惟一字符串标记,而该字符串标记直接对应服务器端session ID,能够在服务器端直接经过session ID获取到session数据,利用中间件将获取到的session数据赋值给request,从而实现小程序端就像支持cookie同样。
若是引入了socket,好比ws,个中过程又要复杂一些,额外引入其余坑须要填埋,下回再表。
PS:以上为项目部分代码,不保证可以彻底运行。