一、登錄流程圖
二、微信小程序端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
dologin:function(callback = () =>{}){ let that = this ; wx.login({ success:function(loginres){ if (loginres){ //獲取用戶信息 wx.getuserinfo({ withcredentials: true , //非必填 默認為true success:function(infores){ console.log(infores, '>>>' ); //請求服務(wù)端的登錄接口 wx.request({ url: api.loginurl, data:{ code:loginres.code, //臨時登錄憑證 rawdata:infores.rawdata, //用戶非敏感信息 signature:infores.signature, //簽名 encryptedata:infores.encrypteddata, //用戶敏感信息 iv:infores.iv //解密算法的向量 }, success:function(res){ console.log( 'login success' ); res = res.data; if (res.result== 0 ){ that.globaldata.userinfo = res.userinfo; wx.setstoragesync( 'userinfo' ,json.stringify(res.userinfo)); wx.setstoragesync( 'loginflag' ,res.skey); console.log( "skey=" +res.skey); callback(); } else { that.showinfo( 'res.errmsg' ); } }, fail:function(error){ //調(diào)用服務(wù)端登錄接口失敗 // that.showinfo('調(diào)用接口失敗'); console.log(error); } }); } }); } else { } } }); } |
微信小程序端發(fā)起登錄請求,攜帶的參數(shù)主要有:
1
2
3
4
5
|
code:loginres.code, //臨時登錄憑證 rawdata:infores.rawdata, //用戶非敏感信息 signature:infores.signature, //簽名 encryptedata:infores.encrypteddata, //用戶敏感信息 iv:infores.iv //解密算法的向量 |
需要的數(shù)據(jù)主要有:
result、userinfo和skey
result用來判斷是否登錄成功,userinfo是用戶的一些信息,保存在緩存中,不用每次都從后臺獲取,skey是用戶登錄態(tài)標識,也放在緩存中,如果skey存在就直接登錄,維護用戶的登錄狀態(tài),具有時效性
三、java后臺
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
@responsebody @requestmapping ( "/login" ) public map<string,object> dologin(model model, @requestparam (value = "code" ,required = false ) string code, @requestparam (value = "rawdata" ,required = false ) string rawdata, @requestparam (value = "signature" ,required = false ) string signature, @requestparam (value = "encryptedata" ,required = false ) string encryptedata, @requestparam (value = "iv" ,required = false ) string iv){ log.info( "start get sessionkey" ); map<string,object> map = new hashmap<string, object>( ); system.out.println( "用戶非敏感信息" +rawdata); jsonobject rawdatajson = json.parseobject( rawdata ); system.out.println( "簽名" +signature); jsonobject sessionkeyopenid = getsessionkeyoropenid( code ); system.out.println( "post請求獲取的sessionandopenid=" +sessionkeyopenid); string openid = sessionkeyopenid.getstring( "openid" ); string sessionkey = sessionkeyopenid.getstring( "session_key" ); system.out.println( "openid=" +openid+ ",session_key=" +sessionkey); user user = userservice.findbyopenid( openid ); //uuid生成唯一key string skey = uuid.randomuuid().tostring(); if (user== null ){ //入庫 string nickname = rawdatajson.getstring( "nickname" ); string avatarurl = rawdatajson.getstring( "avatarurl" ); string gender = rawdatajson.getstring( "gender" ); string city = rawdatajson.getstring( "city" ); string country = rawdatajson.getstring( "country" ); string province = rawdatajson.getstring( "province" ); user = new user(); user.setuid( openid ); user.setcreatetime( new date( ) ); user.setsessionkey( sessionkey ); user.setubalance( 0 ); user.setskey( skey ); user.setuaddress( country+ " " +province+ " " +city ); user.setuavatar( avatarurl ); user.setugender( integer.parseint( gender ) ); user.setuname( nickname ); user.setupdatetime( new date( ) ); userservice.insert( user ); } else { //已存在 log.info( "用戶openid已存在,不需要插入" ); } //根據(jù)openid查詢skey是否存在 string skey_redis = (string) redistemplate.opsforvalue().get( openid ); if (stringutils.isnotblank( skey_redis )){ //存在 刪除 skey 重新生成skey 將skey返回 redistemplate.delete( skey_redis ); } // 緩存一份新的 jsonobject sessionobj = new jsonobject( ); sessionobj.put( "openid" ,openid ); sessionobj.put( "sessionkey" ,sessionkey ); redistemplate.opsforvalue().set( skey,sessionobj.tojsonstring() ); redistemplate.opsforvalue().set( openid,skey ); //把新的sessionkey和oppenid返回給小程序 map.put( "skey" ,skey ); map.put( "result" , "0" ); jsonobject userinfo = getuserinfo( encryptedata, sessionkey, iv ); system.out.println( "根據(jù)解密算法獲取的userinfo=" +userinfo); userinfo.put( "balance" ,user.getubalance() ); map.put( "userinfo" ,userinfo ); return map; } |
獲取openid和sessionkey方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public static jsonobject getsessionkeyoropenid(string code){ //微信端登錄code string wxcode = code; string requesturl = "https://api.weixin.qq.com/sns/jscode2session" ; map<string,string> requesturlparam = new hashmap<string, string>( ); requesturlparam.put( "appid" , "你的小程序appid" ); //小程序appid requesturlparam.put( "secret" , "你的小程序appsecret" ); requesturlparam.put( "js_code" ,wxcode ); //小程序端返回的code requesturlparam.put( "grant_type" , "authorization_code" ); //默認參數(shù) //發(fā)送post請求讀取調(diào)用微信接口獲取openid用戶唯一標識 jsonobject jsonobject = json.parseobject( urlutil.sendpost( requesturl,requesturlparam )); return jsonobject; } |
解密用戶敏感數(shù)據(jù)獲取用戶信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
public static jsonobject getuserinfo(string encrypteddata,string sessionkey,string iv){ // 被加密的數(shù)據(jù) byte [] databyte = base64.decode(encrypteddata); // 加密秘鑰 byte [] keybyte = base64.decode(sessionkey); // 偏移量 byte [] ivbyte = base64.decode(iv); try { // 如果密鑰不足16位,那么就補足. 這個if 中的內(nèi)容很重要 int base = 16 ; if (keybyte.length % base != 0 ) { int groups = keybyte.length / base + (keybyte.length % base != 0 ? 1 : 0 ); byte [] temp = new byte [groups * base]; arrays.fill(temp, ( byte ) 0 ); system.arraycopy(keybyte, 0 , temp, 0 , keybyte.length); keybyte = temp; } // 初始化 security.addprovider( new bouncycastleprovider()); cipher cipher = cipher.getinstance( "aes/cbc/pkcs7padding" , "bc" ); secretkeyspec spec = new secretkeyspec(keybyte, "aes" ); algorithmparameters parameters = algorithmparameters.getinstance( "aes" ); parameters.init( new ivparameterspec(ivbyte)); cipher.init( cipher.decrypt_mode, spec, parameters); // 初始化 byte [] resultbyte = cipher.dofinal(databyte); if ( null != resultbyte && resultbyte.length > 0 ) { string result = new string(resultbyte, "utf-8" ); return json.parseobject(result); } } catch (nosuchalgorithmexception e) { log.error(e.getmessage(), e); } catch (nosuchpaddingexception e) { log.error(e.getmessage(), e); } catch (invalidparameterspecexception e) { log.error(e.getmessage(), e); } catch (illegalblocksizeexception e) { log.error(e.getmessage(), e); } catch (badpaddingexception e) { log.error(e.getmessage(), e); } catch (unsupportedencodingexception e) { log.error(e.getmessage(), e); } catch (invalidkeyexception e) { log.error(e.getmessage(), e); } catch (invalidalgorithmparameterexception e) { log.error(e.getmessage(), e); } catch (nosuchproviderexception e) { log.error(e.getmessage(), e); } return null ; } |
四、流程
1.小程序端發(fā)起請求并攜帶主要參數(shù)
2.java后臺接到/login請求后,根據(jù)code去調(diào)用微信接口獲取用戶唯一標識openid和sessionkey
3.根據(jù)openid查詢mysql數(shù)據(jù)庫,判斷該用戶是否存在,如果不存在將用戶非敏感信息和其他初始化數(shù)據(jù)存入到數(shù)據(jù)庫中,如果已存在,不操作
4.根據(jù)openid查詢redis數(shù)據(jù)庫,判斷openid對應(yīng)的skey是否存在,如果存在則刪除原來老的skey以及對應(yīng)的openid和sessionkey
5.通過uuid生成唯一的skey,用openid做鍵,skey做值,存入到redis中
6.然后把skey做鍵,openid和sessionkey的json串做值也重新存入到redis中
7.根據(jù)解密算法,參數(shù)有encrypteddata、sessionkey和iv,獲取用戶信息userinfo,如果userinfo字段不滿足需要,可通過userinfo.put( “balance”,user.getubalance() );添加所需要的字段和值
8.將微信小程序需要的數(shù)據(jù)封裝到map中,返回給小程序端
1
2
3
4
|
map.put( "skey" ,skey ); map.put( "result" , "0" ); map.put( "userinfo" ,userinfo ); return map; |
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://blog.csdn.net/qq_38977097/article/details/80778105