微信公众号用户认证机制升级方案
背景
- 原认证机制为 cookie方式,缺点如下:
- 不通用,cookie方式仅限于H5或 PC访问,对于APP的访问比较局限;
- 不安全,cookie在请求中可以轻易获取,从而伪造真实请求;
- 不灵活,无法面向第三方接口调用。
2.目前需要设计自有购物流程,面向普通用户,为了更安全灵活通用的认证用户信息,需将cookie方式进行升级,采用Token方式进行用户登录和信息认证。
解决方案:Token机制
认证流程:
图一
具体实现:
如图一所示:
- 前端调用登录API,携带登录信息(公众号为:mobile+verifyCode)
- 服务端 验证verifyCode正确性,如果正确则:
- 生成
SecretKey
存放在member表,用于根据业务参数(文件除外)和签名算法计算Sign
; - 生成
Token+memberId
的KV存放在Redis中,用于 通过Token获取用户信息。 - 返回
SecretKey
、Token
给前端; - 至此,登录流程完成,前端获取了验证所需的所有元素。
- 生成
- 前端请求其他API,除了业务参数外,需要在 Header中存放
Token
信息和用签名算法计算出的签名Sign
,以及时间戳Timestamp
- 服务端得到请求后进行拦截,做权限校验:
- 首先校验时间戳
Timestamp
是否合法(允许与服务器时间误差10S
); - 然后通过Token查询Redis获取memberId,查询该用户的
SecretKey
; - 再取出所有的业务参数(文件除外),按照签名算法计算
Sign
; - 最后和请求Header中的
Sign
进行对比,如果相同请求合法,否则请求非法;
- 首先校验时间戳
- 服务端进行业务逻辑处理,并返回业务处理结果;
- 请求结束。
附录
签名算法
- 将业务参数键名,根据字母表顺序排序后,拼接业务参数值;如
foo=foo&bar=bar
,拼接后得到values:barfoo
; - 然后使用token+path+values+timestamp+secretKey进行拼接,如
token=token
、path=/api/gmall/v1/member
、secretKey=secretKey
、timestamp=1223232
,拼接后为:token/api/gmall/v1/memberbarfoo1223232secretKey
; - 对拼接后的字符串进行MD5,得到的字符串即
Authorization
。
鉴权注解
- 服务端通过在Controller的方法上添加注解
@Authorization
来表明该方法是否需要进行登录信息鉴权,如果没有注解则默认不需要进行登录信息鉴权。
当前用户获取
- 服务端通过
Member member = AuthorizationInterceptor.CURRENT_USER.get();
来获取当前用户信息(包括 userId、nickname、openID等)。
JS请求示例
var settings = {
"async": true,
"crossDomain": true,
"url": "http://www.baidu.com/**",
"method": "POST/GET",
"headers": {
"token": "VDFKGLJKLJDADJKAL243RJLKW",
"timestamp": "12932838293",
"Authorization": "DADLJAD23432HDAKJHDQ2ID",
"content-type": "application/json",
"cache-control": "no-cache"
}
}
$.ajax(settings).done(function (response) {
console.log(response);
});