日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

微信验证以及登录流程

發布時間:2025/6/17 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 微信验证以及登录流程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言: 現在大多數網站項目都支持微信登錄,付款,以及支付寶登錄付款,這種方式也是能夠讓用戶很快速便捷的注冊本網站的賬號,進行登錄,以及后續的操作。相信小伙伴們看完之后,會對怎么與微信或者支付寶服務器打交道有很深的理解,就當做是一個敲門磚吧。那么本篇主要針對微信的驗證登錄來打開通往微信服務器的大門,下一篇會主要講解一下支付寶付款驗證對接。

?本篇為原創,轉載請標出處:http://www.cnblogs.com/gudu1/p/8087130.html?

下面我會使用大量的代碼,代碼中添加完整的注釋來解釋與微信服務器對接的詳細步驟:

首先呢,需要有一個微信公眾號,當然是收費的,不過呢,微信給我們開發人員提供的有微信公眾測試號來進行開發測試,雖然提供功能不是很全,開發測試是夠用了,還是很到位的

微信測試號地址:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

掃碼登陸后呢,就是下面這個樣子了:

上面這個appID 和 appsecret 很重要,正常的公眾號appsecret 一定不要暴露出去,不然是很危險的。

>> URL: 規則 http://服務器地址或者域名/項目驗證接口路由,比如: http://www.mmm.cn/testProject/weChat.do,這個weChat.do 就是要跟微信服務器驗證對接的接口

>> Token:這個是由用戶自己來定義,主要是我們的項目跟微信服務器對接時候需要進行SHA1加密和解密的字段之一,詳細請看官方文檔:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319

>> 域名: 這里就需要使用你自己的域名了,當然域名是要指向能夠被外網訪問到的服務器地址。

當我們在接口配置信息這里點擊提交,微信服務器就會向我們的服務器接口發送消息來進行驗證是否正確。

當然還需要修改一處,這里需要的還是服務器域名:

?

接下來呢,就要看我們的程序跟微信驗證的代碼流程:

這里呢,我使用的 Spring 來做:

import java.io.IOException; import java.io.PrintWriter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.util.wechat.SignUtil;@Controller @RequestMapping("wechat") public class WechatController {private static Logger log = LoggerFactory.getLogger(WechatController.class);@RequestMapping(method = { RequestMethod.GET })public void doGet(HttpServletRequest request, HttpServletResponse response) {log.debug("weixin get...");// 微信加密簽名,signature結合了開發者填寫的token參數和請求中的timestamp參數、nonce參數。String signature = request.getParameter("signature");// 時間戳String timestamp = request.getParameter("timestamp");// 隨機數String nonce = request.getParameter("nonce");// 隨機字符串String echostr = request.getParameter("echostr");// 通過檢驗signature對請求進行校驗,若校驗成功則原樣返回echostr,表示接入成功,否則接入失敗PrintWriter out = null;try {out = response.getWriter();if (SignUtil.checkSignature(signature, timestamp, nonce)) {log.debug("weixin get success....");
          // 我們驗證通過,確定是微信發過來的消息,就將 隨機字符串原樣返回給微信out.print(echostr);}}
catch (IOException e) {e.printStackTrace();} finally {if (out != null)out.close();}} }

?

?微信發過來的消息會到這里,可以看到我們的Controller的RequestMappiing 路由為 "wechat", 這就是我們在微信測試號中配置的接口路由地址,很明顯,這是一個Servlet ,請求的是doGet 方法。

?

上面代碼只是我們的入口,主要驗證邏輯在下面:

import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays;/*** 微信請求校驗工具類*/ public class SignUtil {// 與接口配置信息中的Token要一致private static String token = "mytoken";/*** 驗證簽名* * @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);// 將三個字符串排序之后合并為一個StringBuilder content = new StringBuilder();for (int i = 0; i < arr.length; i++) {content.append(arr[i]);}MessageDigest md = null;String tmpStr = null;try {// 獲得SHA-1 加密的對象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;} }

?

? ? ?細心看的小伙伴肯定已經注意到了, 在方法上面有一個字段就是token,這里一定要跟微信測試號中配置的保持 一致,不相信的同學可以測試著改一個不一致的,保證過不了。

這里的流程就是,微信首先 把我們的 token+時間戳+隨機數 進行一次SHA-1 加密,然后發送給我們的程序,然后我們再進行一次SHA-1加密,然后跟微信發送過來的加密數據進行匹配。我們想象一下,有人故意破壞我們的程序,然后模擬發送數據,能嗎?答案是能,不過他首先得拿到我們的token字段,才能使我們的程序給出正確響應,所以這里的token 配置一定要和微信測試號中配置保持一致。

?

? 好了,既然極影和微信服務器連通了,那么就開始我們的業務需求登錄操作吧。

用戶使用微信登錄,肯定是需要向微信服務器發送登錄請求,然后微信再回調我們的接口,接口獲取微信服務器傳遞過來的信息,確定用戶是否登錄成功,包括用戶的一些數據,比如:昵稱,頭像地址 等等。

業務流程:?

第一步:請求CODE?

  首先要知道這些接口是誰定義的,肯定是微信定義的了,那我們怎么知道向哪個接口發送消息,這就需要查看微信給我們提供的官方文檔了。

  https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect , 該地址是程序向微信發送的第一條請求,請求參數中攜帶code

  下面來分析一下這條URL:

  appid:應用唯一標識,也就是微信測試號中的第一條 appid

  redirect_uri:使用urlEncode對鏈接進行處理,也就是微信服務器回調地址,地址就指向我們程序中處理用戶是否登錄的接口

  response_type:?就填寫 code

?  ?scope:應用授權作用域,擁有多個作用域用逗號(,)分隔,網頁應用目前僅填寫snsapi_login即可

?  ?state:用于保持請求和回調的狀態,授權請求后原樣帶回給第三方。該參數可用于防止csrf攻擊(跨站請求偽造攻擊),建議第三方帶上該參數,可設置為簡單的隨機數加session進行校驗

接下來就貼一下我的程序代碼幫助理解:

import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod;import com.util.wechat.WechatUtil;/*** 獲取關注公眾號之后的微信用戶信息的接口,如果在微信瀏覽器里訪問* https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxd7f6c5b8899fba83&redirect_uri=http://o2o.yitiaojieinfo.com/o2o/wechatlogin/logincheck&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect* 則這里將會獲取到code,之后再可以通過code獲取到access_token 進而獲取到用戶信息* @author xiangze**/ @Controller @RequestMapping("wechatlogin") public class WechatLoginController {private static Logger log = LoggerFactory.getLogger(WechatLoginController.class);private static final String FRONTEND = "1";private static final String SHOPEND = "2";@Autowiredprivate PersonInfoService personInfoService;@Autowiredprivate WechatAuthService wechatAuthService;@RequestMapping(value = "/logincheck", method = { RequestMethod.GET })public String doGet(HttpServletRequest request, HttpServletResponse response) {log.debug("weixin login get...");// 獲取微信公眾號傳輸過來的code,通過code可獲取access_token,進而獲取用戶信息String code = request.getParameter("code");// 這個state可以用來傳我們自定義的信息,方便程序調用,這里也可以不用String roleType = request.getParameter("state");log.debug("weixin login code:" + code);WechatUser user = null;String openId = null;WechatAuth auth = null;if (null != code) {UserAccessToken token;try {// 通過code獲取access_tokentoken = WechatUtil.getUserAccessToken(code);log.debug("weixin login token:" + token.toString());// 通過token獲取accessTokenString accessToken = token.getAccessToken();// 通過token獲取openIdopenId = token.getOpenId();// 通過access_token和openId獲取用戶昵稱等信息user = WechatUtil.getUserInfo(accessToken, openId);log.debug("weixin login user:" + user.toString());request.getSession().setAttribute("openId", openId);auth = wechatAuthService.getWechatAuthByOpenId(openId);} catch (IOException e) {log.error("error in getUserAccessToken or getUserInfo or findByOpenId: " + e.toString());e.printStackTrace();}}// 若微信帳號為空則需要注冊微信帳號,同時注冊用戶信息if (auth == null) {PersonInfo personInfo = WechatUtil.getPersonInfoFromRequest(user);auth = new WechatAuth();auth.setOpenId(openId);if (FRONTEND.equals(roleType)) {personInfo.setUserType(1);} else {personInfo.setUserType(2);}auth.setPersonInfo(personInfo);WechatAuthExecution we = wechatAuthService.register(auth);if (we.getState() != WechatAuthStateEnum.SUCCESS.getState()) {return null;} else {personInfo = personInfoService.getPersonInfoById(auth.getPersonInfo().getUserId());request.getSession().setAttribute("user", personInfo);}} else {request.getSession().setAttribute("user", auth.getPersonInfo());}// 若用戶點擊的是前端展示系統按鈕則進入前端展示系統if (FRONTEND.equals(roleType)) {return "frontend/index";} else {return "shop/shoplist";}} }

?

?

第二步:通過code獲取用戶access_token

  調用接口:https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code?

  代碼:

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ConnectException; import java.net.URL; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper;/*** 微信工具類* * @author xiangze**/ public class WechatUtil {private static Logger log = LoggerFactory.getLogger(WechatUtil.class);/*** 獲取UserAccessToken實體類* * @param code* @return* @throws IOException*/public static UserAccessToken getUserAccessToken(String code) throws IOException {// 測試號信息里的appIdString appId = "你的微信測試號appid";log.debug("appId:" + appId);// 測試號信息里的appsecretString appsecret = "你的微信測試號appsecret";log.debug("secret:" + appsecret);// 根據傳入的code,拼接出訪問微信定義好的接口的URLString url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + appsecret+ "&code=" + code + "&grant_type=authorization_code";// 向相應URL發送請求獲取token json字符串String tokenStr = httpsRequest(url, "GET", null);log.debug("userAccessToken:" + tokenStr);UserAccessToken token = new UserAccessToken();ObjectMapper objectMapper = new ObjectMapper();try {// 將json字符串轉換成相應對象token = objectMapper.readValue(tokenStr, UserAccessToken.class);} catch (JsonParseException e) {log.error("獲取用戶accessToken失敗: " + e.getMessage());e.printStackTrace();} catch (JsonMappingException e) {log.error("獲取用戶accessToken失敗: " + e.getMessage());e.printStackTrace();} catch (IOException e) {log.error("獲取用戶accessToken失敗: " + e.getMessage());e.printStackTrace();}if (token == null) {log.error("獲取用戶accessToken失敗。");return null;}return token;}/*** 發起https請求并獲取結果* * @param requestUrl* 請求地址* @param requestMethod* 請求方式(GET、POST)* @param outputStr* 提交的數據* @return json字符串*/public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {StringBuffer buffer = new StringBuffer();try {// 創建SSLContext對象,并使用我們指定的信任管理器初始化TrustManager[] tm = { new MyX509TrustManager() };SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");sslContext.init(null, tm, new java.security.SecureRandom());// 從上述SSLContext對象中得到SSLSocketFactory對象SSLSocketFactory ssf = sslContext.getSocketFactory();URL url = new URL(requestUrl);HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();httpUrlConn.setSSLSocketFactory(ssf);httpUrlConn.setDoOutput(true);httpUrlConn.setDoInput(true);httpUrlConn.setUseCaches(false);// 設置請求方式(GET/POST) httpUrlConn.setRequestMethod(requestMethod);if ("GET".equalsIgnoreCase(requestMethod))httpUrlConn.connect();// 當有數據需要提交時if (null != outputStr) {OutputStream outputStream = httpUrlConn.getOutputStream();// 注意編碼格式,防止中文亂碼outputStream.write(outputStr.getBytes("UTF-8"));outputStream.close();}// 將返回的輸入流轉換成字符串InputStream inputStream = httpUrlConn.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String str = null;while ((str = bufferedReader.readLine()) != null) {buffer.append(str);}bufferedReader.close();inputStreamReader.close();// 釋放資源 inputStream.close();inputStream = null;httpUrlConn.disconnect();log.debug("https buffer:" + buffer.toString());} catch (ConnectException ce) {log.error("Weixin server connection timed out.");} catch (Exception e) {log.error("https request error:{}", e);}return buffer.toString();} }

?

? 因為我們發送的是https請求,所以還需要有這么一個工具方法,發起 https 請求。。。

OK,以上就是微信驗證以及登錄的全過程,可能并不是很詳細,不過理解這個過程應該是可以了,那么下篇會講解一下支付寶付款的流程以及代碼。

?

              The End。。。。。。

?

轉載于:https://www.cnblogs.com/gudu1/p/8087130.html

總結

以上是生活随笔為你收集整理的微信验证以及登录流程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。