用ssm進行微信開發,實現微信登入驗證功能
阿新 • • 發佈:2019-02-06
1.微信測試號後臺配置
注意,這個配置要成功,否則是會顯示配置失敗的。後臺怎麼寫,看下面
2.後臺程式碼
2.1驗證token的程式碼
控制器裡:
@RequestMapping(value = "/wxcheck") public void check(Model model, HttpServletRequest request, HttpServletResponse response)throws IOException { boolean isGet = request.getMethod().toLowerCase().equals("get"); PrintWriter print; if(isGet){ // 微信加密簽名 String signature = request.getParameter("signature"); // 時間戳 String timestamp = request.getParameter("timestamp"); // 隨機數 String nonce = request.getParameter("nonce"); // 隨機字串 String echostr = request.getParameter("echostr"); // 通過檢驗signature對請求進行校驗,若校驗成功則原樣返回echostr,表示接入成功,否則接入失敗 if (signature != null && WechatUtil.checkSignature(signature, timestamp, nonce)) { try { print = response.getWriter(); print.write(echostr); print.flush(); } catch (IOException e) { e.printStackTrace(); } } } }
WechatUtil這個工具類:
public class WechatUtil { /** * 與介面配置資訊中的Token要一致 */ private static String token = "20180806"; /** * 驗證簽名 * * @param signature * @param timestamp * @param nonce * @return */ public static boolean checkSignature(String signature, String timestamp, String nonce) { String[] arr = new String[] { token, timestamp, nonce }; // 將token、timestamp、nonce三個引數進行字典序排序 // Arrays.sort(arr); sort(arr); StringBuilder content = new StringBuilder(); for (int i = 0; i < arr.length; i++) { content.append(arr[i]); } MessageDigest md = null; String tmpStr = null; try { md = MessageDigest.getInstance("SHA-1"); // 將三個引數字串拼接成一個字串進行sha1加密 byte[] digest = md.digest(content.toString().getBytes()); tmpStr = byteToStr(digest); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } content = null; // 將sha1加密後的字串可與signature對比,標識該請求來源於微信 return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false; } /** * 將位元組陣列轉換為十六進位制字串 * * @param byteArray * @return */ private static String byteToStr(byte[] byteArray) { String strDigest = ""; for (int i = 0; i < byteArray.length; i++) { strDigest += byteToHexStr(byteArray[i]); } return strDigest; } /** * 將位元組轉換為十六進位制字串 * * @param mByte * @return */ private static String byteToHexStr(byte mByte) { char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; char[] tempArr = new char[2]; tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; tempArr[1] = Digit[mByte & 0X0F]; String s = new String(tempArr); return s; } public static void sort(String a[]) { for (int i = 0; i < a.length - 1; i++) { for (int j = i + 1; j < a.length; j++) { if (a[j].compareTo(a[i]) < 0) { String temp = a[i]; a[i] = a[j]; a[j] = temp; } } } } }
這麼一來,微信通過token驗證我們的伺服器就能通過了。
2.獲取微信授權資訊
首先按鈕的格式:這個是比較麻煩的地方,格式必須一模一樣
{ "button": [ { "type": "click", "name": "暢迪用法", "key": "1" }, { "name": "常見問題", "sub_button": [ { "type": "view", "name": "關於過敏性疾病", "url": "http://www.wolwobiotech.com/web2016/1.html" }, { "type": "view", "name": "關於脫敏治療", "url": "http://www.wolwobiotech.com/web2016/2.html" }, { "type": "view", "name": "暢迪相關常見問題", "url": "http://www.wolwobiotech.com/web2016/4.html" } ] }, { "name":"個人中心", "sub_button":[ { "type": "view", "name": "測試", "url" : "https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxXXXXX95&redirect_uri=http%3A%2F%2FXXXXXXXXXXcom%2Flxxxxxxe%2Fauth&response_type=code&scope=snsapi_base&state=123#wechat_redirect" }, { "type": "click", "name": "我要提問", "key" : "103" } ] } ] }
我使用的是基本方法不獲取userinfor,是默認同意授權的,控制器裡的寫法
@RequestMapping(value = "/auth")
public void wxAuth(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
// 使用者同意授權後,能獲取到code
String code = request.getParameter("code");
String state = request.getParameter("state");
String url= "";
// 使用者同意授權
if (!"authdeny".equals(code)) {
// 獲取網頁授權access_token
WeixinOauth2Token weixinOauth2Token = WechatUtil.getOauth2AccessToken("id", "密碼", code);
// 網頁授權介面訪問憑證
String accessToken = weixinOauth2Token.getAccessToken();
// 使用者標識
String openId = weixinOauth2Token.getOpenId();
String ip = IpUtil.getIpAddr(request);
WxOpenid wxOpenid = new WxOpenid();
wxOpenid.setIp(ip);
wxOpenid.setCreatTime(new Date());
wxOpenid.setOpenid(openId);
int i = wxOpenidService.insertSelective(wxOpenid);
System.out.println(">>>>>>>>>>>>>>>>>>>>"+ip);
// // 獲取使用者資訊
// SNSUserInfo snsUserInfo = AdvancedUtil.getSNSUserInfo(accessToken, openId);
// 設定要傳遞的引數
// request.setAttribute("snsUserInfo", snsUserInfo);
// request.setAttribute("state", state);
}
url = "http://xxx/xxx/";
// 跳轉到langya前臺
response.sendRedirect(url);
}
用到的工具類:
/**
* 獲取網頁授權憑證
*
* @param appId 公眾賬號的唯一標識
* @param appSecret 公眾賬號的金鑰
* @param code
* @return WeixinAouth2Token
*/
public static WeixinOauth2Token getOauth2AccessToken(String appId, String appSecret, String code) {
WeixinOauth2Token wat = new WeixinOauth2Token();
// 拼接請求地址
String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
requestUrl = requestUrl.replace("APPID", appId);
requestUrl = requestUrl.replace("SECRET", appSecret);
requestUrl = requestUrl.replace("CODE", code);
// 獲取網頁授權憑證
JSONObject jsonObject = HttpCommonUtil.httpsRequest(requestUrl, "GET", null);
if (null != jsonObject) {
try {
wat.setAccessToken(jsonObject.getString("access_token"));
wat.setExpiresIn(jsonObject.getInteger("expires_in"));
wat.setRefreshToken(jsonObject.getString("refresh_token"));
wat.setOpenId(jsonObject.getString("openid"));
wat.setScope(jsonObject.getString("scope"));
} catch (Exception e) {
// wat = null;
// int errorCode = jsonObject.getInteger("errcode");
// String errorMsg = jsonObject.getString("errmsg");
// log.error("獲取網頁授權憑證失敗 errcode:{} errmsg:{}", errorCode, errorMsg);
}
}
return wat;
}
還有一個網頁授權資訊的實體類:
/**
* 類名: WeixinOauth2Token </br>
* 描述: 網頁授權資訊 </br>
* 開發人員: fr</br>
* 釋出版本:V1.0 </br>
*/
public class WeixinOauth2Token {
// 網頁授權介面呼叫憑證
private String accessToken;
// 憑證有效時長
private int expiresIn;
// 用於重新整理憑證
private String refreshToken;
// 使用者標識
private String openId;
// 使用者授權作用域
private String scope;
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public int getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(int expiresIn) {
this.expiresIn = expiresIn;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public String getOpenId() {
return openId;
}
public void setOpenId(String openId) {
this.openId = openId;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
還有一個傳送http請求的工具類
package com.wolwo.base.util;
import com.alibaba.fastjson.JSONObject;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.URL;
import java.security.SecureRandom;
import javax.net.ssl.*;
public class HttpCommonUtil {
/**
* 傳送https請求
*
* @param requestUrl 請求地址
* @param requestMethod 請求方式(GET、POST)
* @param outputStr 提交的資料
* @return JSONObject(通過JSONObject.get(key)的方式獲取json物件的屬性值)
*/
public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
JSONObject jsonObject = null;
try {
// 建立SSLContext物件,並使用我們指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new SecureRandom());
// 從上述SSLContext物件中得到SSLSocketFactory物件
SSLSocketFactory ssf = sslContext.getSocketFactory();
URL url = new URL(requestUrl);
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 設定請求方式(GET/POST)
conn.setRequestMethod(requestMethod);
// 當outputStr不為null時向輸出流寫資料
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意編碼格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 從輸入流讀取返回內容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 釋放資源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
jsonObject = JSONObject.parseObject(buffer.toString());
} catch (ConnectException ce) {
// log.error("連線超時:{}", ce);
} catch (Exception e) {
// log.error("https請求異常:{}", e);
}
return jsonObject;
}
}
package com.wolwo.base.util;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;
/**
* 類名: MyX509TrustManager </br>
* 描述:信任管理器 </br>
* 開發人員: fr</br>
* 釋出版本:V1.0 </br>
*/
public class MyX509TrustManager implements X509TrustManager {
// 檢查客戶端證書
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
// 檢查伺服器端證書
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
// 返回受信任的X509證書陣列
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
這麼一來就行了