IT忍者神龜之Java基於微信公衆號接口實現授權登錄源碼及原理分析

微信公衆號授權登錄操作前提必須註冊微信公衆平臺賬號,注意的是訂閱號不支持授權登錄操作,因此對於個人開發者註冊的訂閱號是無法實現的,必須註冊企業號的微信平臺賬號而具體註冊流程就不詳細介紹了,有什麼疑問可去微信公衆號平臺查看具體的文檔。


接下來講述一下具體的微信授權登錄流程,打開微信開發文檔官網(https://mp.weixin.qq.com/wiki),“微信網頁開發”中找到“微信網頁授權”,其中詳細介紹了微信授權登錄實現,如圖:

2.png


AppId和AppSecret參數見下圖:

1.png


網頁授權流程分爲四步:

1、引導用戶進入授權頁面同意授權,獲取code 

2、通過code換取網頁授權access_token(與基礎支持中的access_token不同) 

3、如果需要,開發者可以刷新網頁授權access_token,避免過期 

4、通過網頁授權access_token和openid獲取用戶基本信息(支持UnionID機制) 


步驟一:首先需要獲取code,具體發送鏈接如下:https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

其中參數appid、redirect_uri、response_type、scope、state,具體說明如下圖:

3.png

注意:當scope爲snsapi_base(靜默授權) ,就不會彈出授權頁面;而scope爲snsapi_userinfo(手動授權)時,是彈出授權頁面的,可以獲取用戶的相關信息。

微信授權有兩種網頁授權方式

第一種靜默授權:不會給登錄用戶任何提示直接返回用戶code,但如果登錄用戶存在關注公衆號的情況下,無法拿到登錄用戶的全部信息

以snsapi_base爲scope發起的網頁授權,是用來獲取進入頁面的用戶的openid的,並且是靜默授權並自動跳轉到回調頁的。用戶感知的就是直接進入了回調頁(往往是業務頁面)

第二種手動授權:彈出授權頁面,登錄用戶點擊確定後可獲取登錄用戶的信息

以snsapi_userinfo爲scope發起的網頁授權,是用來獲取用戶的基本信息的。但這種授權需要用戶手動同意,並且由於用戶同意過,所以無須關注,就可在授權後獲取該用戶的基本信息。 

參考案例:

靜默授權 https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect

手動授權 https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect


步驟二:通過code值獲取網頁授權access_token票據

登錄用戶每次授權所攜帶的code都不一樣,code只能使用一次,5分鐘自動過期。

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

其中參數appid、secret、code、grant_type,具體說明如下圖:

4.png


步驟三:刷新access_token(如果需要)

由於access_token擁有較短的有效期,當access_token超時後,可以使用refresh_token進行刷新,refresh_token有效期爲30天,當refresh_token失效之後,需要用戶重新授權。


步驟四:拉取用戶信息(需scope爲 snsapi_userinfo)

獲取用戶信息網頁授權作用域爲snsapi_userinfo,此時開發者可以通過access_token和openid獲取用戶信息。具體鏈接如下:https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

其中參數access_token、openid、lang,具體說明如下圖:

5.png


具體實現微信公衆號授權登錄代碼,通過填寫的回調url進入我們的後臺登錄調用方法,代碼如下:

public void weixinLogin(HttpServletRequest request,HttpServletResponse response) throws Exception {  
  Map<String, String[]> params = request.getParameterMap();//針對get獲取get參數  
  String[] codes = params.get("code");//拿到的code的值  
  String code = codes[0];//code  
  /*
   * 拼寫微信api請求地址並通過微信的appId和微信公衆號的AppSecret
   * 以及授權回調的code獲取用戶的openid和access_token
   */  
  String requestUrl = " https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID
  &redirect_uri=APPSECRET&response_type=code&scope=snsapi_userinfo&state=STATE"
  .replace("APPID",APPID).replace("APPSECRET", AppSecret).replace("CODE", code);  
  String requestResult = doGet(requestUrl);
  JSONObject jsons = JSON.parseObject(requestResult);//結果轉換成JSON對象  
  if(jsons == null || jsons.getInteger("errcode") != null || jsons.getString("openid") == null) {  
    throw NoResultException();//自定義異常類
  }  
  String openid = jsons.getString("openid");  
  //注意:公衆號通用的access_token和登錄用戶的access_token是有區別的
  //微信公衆號的通用access_token每天只能取2000次 每次token有效期是7200S  
  requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token
  ?appid=APPID&secret=APPSECRET&code=CODE&grant_type=authorization_code"
  .replace("APPID", APPID).replace("APPSECRET", AppSecret);   
  requestResult = doGet(requestUrl);   
  JSONObject weixinToken = JSON.parseObject(requestResult);  
  if(jsonObject == null){  
      throw NoResultException();//自定義異常類,獲取我們公衆號token失敗  
  }  
  String wxgzhToken =  accessToken.setToken(jsonObject.getString("access_token"));  
  requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN
  &openid=OPENID&lang=zh_CN".replace("ACCESS_TOKEN", wxgzhToken).replace("OPENID", openid);  
  requestResult = doGet(requestUrl);   
  JSONObject user = JSON.parseObject(requestResult);  
  if(user == null || user.getInteger("errcode") != null ) {  
      throw NoResultException();//自定義異常類
  }  
  //把這些信息存在我們的數據庫中然後跳轉到我們前臺頁面 
}  
/**
 * get方式
 * @param url
 * @author blog.yoodb.com
 * @return
 */
public static String doGet(String url) {
  String responseMsg = "";
  HttpClient httpClient = new HttpClient();
  GetMethod getMethod = new GetMethod(url);
  getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER
    ,new DefaultHttpMethodRetryHandler());
  try {
    httpClient.executeMethod(getMethod);
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    InputStream in = getMethod.getResponseBodyAsStream();
    int len = 0;
    byte[] buf = new byte[1024];
    while((len=in.read(buf))!=-1){
      out.write(buf, 0, len);
    }
    responseMsg = out.toString("UTF-8");
  } catch (HttpException e) {
    e.printStackTrace();
  } catch (IOException e) {
    e.printStackTrace();
  } finally {
    //釋放連接
    getMethod.releaseConnection();
  }
  return responseMsg;
}

如果登錄成功授權之後會返回正確的json格式數據,反之失敗返回相對應的錯誤碼。

發佈了656 篇原創文章 · 獲贊 101 · 訪問量 51萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章