小程序登錄、微信網頁授權(Java版)
首先呢,“登錄”、“授權”、“授權登錄”,是一樣的意思,不用糾結。
寫小程序授權登錄的代碼前,需要了解清楚openid與unionid的區別,這裏再簡單介紹一下:
- 騰訊有個 “微信·開放平臺”,只有企業才能註冊賬號,可理解爲微信體系裏,最頂級的賬號。官網地址:https://open.weixin.qq.com
- 除了這個微信開放平臺,還有另一個叫做 “微信公衆平臺”,可註冊四種賬號,包括服務號、訂閱號、小程序、企業微信。也就是說,公衆號(服務號和訂閱號可統稱爲公衆號)佔一個賬號,小程序也佔一個賬號。在沒有綁定開放平臺前,小程序授權登錄只能拿到用戶的openid。官網地址:https://mp.weixin.qq.com
- 小程序可綁定在公衆號下,公衆號可以綁定在微信開放平臺下,小程序也可以綁定在微信開放平臺下。(好像有點小繞)簡單點說,所有的公衆平臺賬號都需要綁定在 “開放平臺” 下,纔可獲得的unionid,這是打通同個企業下所有微信公衆賬號的最有效方法(官方推薦)
- 更加具體的可自行百度...
一、以下爲小程序登錄的代碼:
-
方式一:通過code調用code2session接口獲得message,包含openid、session_key,滿足條件的情況下還能直接獲得unionid
- 條件如下:(存在侷限性)
- 官方說明UnionID獲取途徑,如果開發者帳號下存在同主體的公衆號,並且該用戶已經關注了該公衆號。開發者可以直接通過 wx.login + code2Session 獲取到該用戶 UnionID,無須用戶再次授權。
- 開發者帳號下存在同主體的公衆號或移動應用,並且該用戶已經授權登錄過該公衆號或移動應用。也可通過code2session獲取該用戶的 UnionID。
/**
* Author: huanglp
* Date: 2018-11-28
*/
public class WeiXinUtils {
private static Logger log = LoggerFactory.getLogger(WeiXinUtils.class);
/**
* 通過前端傳過來的code, 調用小程序登錄接口, 獲取到message並返回 (包含openid session_key等)
*
* @param code
* @return
*/
public static JSONObject login(String code) {
log.info("==============小程序登錄方法開始================");
WxMiniProperties properties = WeiXinPropertiesUtils.getWxMiniProperties();
String url = properties.getInterfaceUrl() + "/sns/jscode2session?appid="
+ properties.getAppId() + "&secret=" + properties.getAppSecret()
+ "&js_code=" + code + "&grant_type=authorization_code";
JSONObject message;
try {
// RestTemplate是Spring封裝好的, 挺好用, 可做成單例模式
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject(url, String.class);
message = JSON.parseObject(response);
} catch (Exception e) {
log.error("微信服務器請求錯誤", e);
message = new JSONObject();
}
log.info("message:" + message.toString());
log.info("==============小程序登錄方法結束================");
return message;
// 後續, 可獲取openid session_key等數據, 以下代碼一般放在Service層
//if (message.get("errcode") != null) {
// throw new ValidationException(message.toString());
//}
//String openid = message.get("openid").toString();
//String sessionKey = message.get("session_key").toString();
//...
}
}
- 補充1: WeiXinPropertiesUtils工具類
public class WeiXinPropertiesUtils {
// 微信小程序配置
private static WxMiniProperties miniProperties;
// 微信公衆號配置
private static WxProperties wxProperties;
private static void init() {
if (miniProperties == null) {
miniProperties = ContextLoader.getCurrentWebApplicationContext()
.getBean(WxMiniProperties.class);
}
if (wxProperties == null) {
wxProperties = ContextLoader.getCurrentWebApplicationContext()
.getBean(WxProperties.class);
}
}
public static WxMiniProperties getWxMiniProperties() {
init();
return miniProperties;
}
public static WxProperties getWxProperties() {
init();
return wxProperties;
}
}
- 補充2: WxMiniProperties配置類
@Data
@Component
@ConfigurationProperties(prefix = "luwei.module.wx-mini")
public class WxMiniProperties {
private String appId;
private String appSecret;
private String interfaceUrl;
}
到此已能通過code獲取到用戶的openid和session_key,但若不滿足條件,即使將小程序綁定到微信開放平臺上,也獲取不到unionid,所以此方式不穩定,推薦使用解密的方式獲取數據。
- 方式二:通過解密的方式獲取用戶unionid
/**
* 通過encryptedData,sessionKey,iv獲得解密信息, 擁有用戶豐富的信息, 包含openid,unionid,暱稱等
*/
public static JSONObject decryptWxData(String encryptedData, String sessionKey, String iv) throws Exception {
log.info("============小程序登錄解析數據方法開始==========");
String result = AesCbcUtil.decrypt(encryptedData, sessionKey, iv, "UTF-8");
JSONObject userInfo = new JSONObject();
if (null != result && result.length() > 0) {
userInfo = JSONObject.parseObject(result);
}
log.info("result: " + userInfo);
log.info("============小程序登錄解析數據方法結束==========");
return userInfo;
}
- 補充1: AesCbcUtil工具類,直接複製即可,需要添加bouncycastle依賴。BouncyCastle是一個開源的加解密解決方案,官網可查看http://www.bouncycastle.org/
package com.luwei.common.utils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Security;
/**
* Updated by huanglp
* Date: 2018-11-28
*/
public class AesCbcUtil {
static {
Security.addProvider(new BouncyCastleProvider());
}
/**
* AES解密
*
* @param data //被加密的數據
* @param key //加密祕鑰
* @param iv //偏移量
* @param encoding //解密後的結果需要進行的編碼
*/
public static String decrypt(String data, String key, String iv, String encoding) {
// org.apache.commons.codec.binary.Base64
byte[] dataByte = Base64.decodeBase64(data);
byte[] keyByte = Base64.decodeBase64(key);
byte[] ivByte = Base64.decodeBase64(iv);
try {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
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) {
return new String(resultByte, encoding);
}
return null;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
到此已經獲取到 JSONObject類型的 userInfo,包含openid,unionid,暱稱,頭像等數據
後續可以將用戶信息保存到數據庫,再返回給前端一個token即可,shiro經過公司封裝了一層,代碼如下:
...
// 獲得用戶ID
int userId = wxUser.getWxUserId();
shiroTokenService.afterLogout(userId);
String uuid = UUID.randomUUID().toString();
String token = StringUtils.deleteAny(uuid, "-") + Long.toString(System.currentTimeMillis(), Character.MAX_RADIX);
shiroTokenService.afterLogin(userId, token, null);
return token;
二、以下爲公衆號(網頁)授權的代碼:
網頁授權更加簡單,可查看 官方文檔
需添加 riversoft 相關依賴包,公衆號網頁授權,只需要將公衆號綁定了開放平臺,就能獲取到unionid及其他用戶信息。
public static OpenUser webSiteLogin(String code, String state) {
log.info("============微信公衆號(網頁)授權開始===========");
WxProperties properties = WeiXinPropertiesUtils.getWxProperties();
AppSetting appSetting = new AppSetting(properties.getAppId(), properties.getAppSecret());
OpenOAuth2s openOAuth2s = OpenOAuth2s.with(appSetting);
AccessToken accessToken = openOAuth2s.getAccessToken(code);
// 獲取用戶信息
OpenUser openUser = openOAuth2s.userInfo(accessToken.getAccessToken(), accessToken.getOpenId());
log.info("============微信公衆號(網頁)授權結束===========");
return openUser;
// 後續, 可將用戶信息保存
// 最後一步, 生成token後, 需重定向回頁面
//return "redirect:" + state + "?token=" + token;
}
署名
廣州蘆葦科技Java開發團隊
蘆葦科技-廣州專業互聯網軟件服務公司
抓住每一處細節 ,創造每一個美好
關注我們的公衆號,瞭解更多
想和我們一起奮鬥嗎?lagou搜索“ 蘆葦科技 ”或者投放簡歷到 [email protected] 加入我們吧
關注我們,你的評論和點贊對我們最大的支持