Skip to main content
 首页 » 编程设计

微信小程序之dajngo后端开发

2022年08月01日142qq号

微信小程序后端开发

  • 微信小程序的后端与普通web 后端的区别
  • 微信小程序登录流程
  • 解决小程序post 问题

微信小程序的后端与普通web 后端的区别

微信小程序与普通的restful api 大致上相同,需注意以下几点限制
1 必须使用https 协议请求后端服务器
2 不支持cookie
3 不支持django 内置的user 登录,因为它使用的是微信用户系统,可以使用,一般要重写,

对应方法:

1去godaddy 网站申请https 证书,下载使用nginx 指定即可,
3可以使用JWT 来保证用户的在线验证,使用pyjwt 实现用户登录/鉴权的组件
或者使用django 内置user 方便,openid做用户名,密码用长随机数;登录时用直接把code传到后端,后端拿着code换session_info,从里面找到openid查user,然后把user传给django-jwt,手动生成jwt返回小程序

jwt jsonwebtoken

是一段带签名的json 格式的数据,其中定义了一种紧凑 (compact) 且自包含(self-contained)的方式用于以JSON对象的形式在多方之间传递信息。信息可以被核实和信任,因为它经过了数字签名。JWT既可以使用密钥(采用HMAC算法),也可以使用公私钥(采用RSA算法)进行签名。*

什么时候需要jwt

http 协议是无状态的,用于前后端分离模式,后端趋于服务化,提供相应操作的接口,例如restful api ,它倡导的就是无状态,无状态可以用 jwt 来实现,利用jwt 将用户状态权限放到客户端,服务端,根据传过去的token 来判断是否有访问这个资源的权限。

jwt 组成

jwt包含了三部分,用.进行分隔:
- 头部(header)
- 载荷(payload)
- 签名(Signature)

生成token

先利用一个数组保存这三个部门,const res=[];得到这三部分再利用res.join('.')来生成token

头部一般分为俩部分,token的类型和加密算法

const header={ 
   alg:'HS256', 
   typ:'JWT', 
};

而后将,这个进行序列化并且转化为base64编码,需要注意的是jwt中对应的base64并不是一个严格意义上的base64,由于token有可能被做为url,而base64中的+/=三个字符会被转义,导致url变得更长,所以token的base64会将+转化为-、/转化为_、删除=。
根据这个规则,来实现一下生成符合要求的base64的函数:

const getBase64UrlEscape = str => ( 
  str.replace(/\+/g, '-') 
    .replace(/\//g, '_') 
    .replace(/=/g, '') 
); 
 
const getBase64Url = data => getBase64UrlEscape( 
  new Buffer(JSON.stringify(data)).toString('base64') 
);

生成header

res.push(getBase64Url(header)); 

载荷

const payload = { 
    username: 'zp1996', 
    id: 1, 
    authority: 32 
};

转为base64编码

res.push(getBase64Url(payload));

签名

签名就是将编码后的头部,载荷利用相应的秘钥进行加密

sha256( 
   `${
   base64UrlEncode(header)}.${
   base64UrlEncode(payload)}`, 
    secret 
)

jwt 生成签名的方式 hmac 与 sign

const cryptoMethod = { 
  hmac: (method, key, input) => crypto.createHmac(method, key).update(input).digest('base64'), 
  sign: (method, input) => crypto.createSign(method).update(input).sign(key, 'base64') 
};

例如

const sign = (input, key, method, type) => getBase64UrlEscape( 
  cryptoMethod[type](method, key, input) 
); 
 
/* 
 * payload 载荷 
 * key 密钥 
 * algorithm 加密算法 
 * type 采用何种类型  hmac or sign 
 */ 
jwt.sign = (payload, key, algorithm = 'HS256', options = {}) => { 
  const signMethod = algorithmMap[algorithm], 
    signType = typeMap[algorithm], 
    header = { 
      typ: 'JWT', 
      alg: algorithm 
    }, 
    res = []; 
  options && options.header && Object.assign(header, options.header); 
  res.push(getBase64Url(header)); 
  res.push(getBase64Url(payload)); 
  res.push(sign(res.join('.'), key, signMethod, signType)); 
  return res.join('.'); 
};

再解析token

const decodeBase64Url = str => JSON.parse( 
  new Buffer(getBase64UrlUnescape(str), 'base64').toString() 
); 
jwt.decode = (token) => { 
  const segments = token.split('.'); 
  return { 
    header: decodeBase64Url(segments[0]), 
    payload: decodeBase64Url(segments[1]) 
  }; 
};

利用秘钥来验证

const verifyMethod = { 
  hmac: (input, key, method, signStr) => signStr === sign(input, key, method, 'hmac'), 
  sign: (input, key, method, sign) => { 
    return crypto.createVerify(method) 
      .update(input) 
      .verify(key, getBase64UrlUnescape(sign), 'base64'); 
  } 
};

小程序登录流程

客户端请求用户授权
用户授权成功
客户端或得到用户基本信息(包括code,没有openid的用户明文信息, 有openid的加密后的信息, 解密向量iv)
客户端把返回的信息发送到服务器
服务器使用code去微信服务器换取session_key
服务器用这个session_key+iv去解密用户密文, 得到用户完整信息(基本+openid)
将用户在服务器登录, 维持用户session(这里的失效时间微信约定是30天)
微信用户登录后, 返回客户端token, 并在缓存创建用户的session信息
客户端请求时附加http头 Authorization=JWT
使用中间件检验http头的token, 审查通过则在request上追加一个 jwt_user属性(这里不想覆盖django自带user), 同时去缓存寻找这个用户的session信息, 加载到 request.jwt_session, 审查如果不通过则jwt_user设置为None, jwt_session为一个空的session对象
使用认证方法, 对于需要进行登录的接口检验用户是否为 None


本文参考链接:https://blog.csdn.net/zhplz123/article/details/81221356