微信授權登錄


1. 微信登錄的兩種實現方式

  第一種是基於微信公眾號進行登錄,第二種是基於微信開放平台進行登錄。

  原因是微信登錄不同於QQ登錄和微博登錄,微信登錄沒有提供輸入賬密碼登錄功能。微信只提供了掃碼登錄功能,如果是PC端進行登錄的話可以用手機進行掃碼,但是如果是手機端打開二維碼是不能進行掃碼的,即便是長按二維碼識別功能,但是非常不友好。

2.微信登錄的實現方式也有兩種

  第一種是沒有自己的賬號體系,直接拉取微信用戶信息來進行網站登錄。

  第二種是有自己的賬號體系,授權成功后需要綁定自己的賬號。

  兩種實現方式都可以,只是在向session中存用戶信息的時候是存用戶獲取的微信信息還是根據獲取的微信信息(可以根據openID和nickname進行對應查詢用戶)轉換為自己系統內對應的賬戶信息。

3.基於微信公眾號進行授權登錄

1.簡介

  如果用戶在微信客戶端中訪問第三方網頁,公眾號可以通過微信網頁授權機制,來獲取用戶基本信息,進而實現業務邏輯。

總的來說,分為四部:

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

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

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

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

 

2.進行授權

  利用授權的微信公眾號(如果沒有可以用開發者工具的微信公眾號測試賬號)。

1.到接口設置修改域名

 

 

2. 邏輯分析(刷新access_token暫時不考慮)

第一步:用戶同意授權,獲取code

接口地址如下:

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

   尤其注意:由於授權操作安全等級較高,所以在發起授權請求時,微信會對授權鏈接做正則強匹配校驗,如果鏈接的參數順序不對,授權頁面將無法正常訪問

參數說明如下:

 

下圖為scope等於snsapi_userinfo時的授權頁面:

 

如果用戶同意授權,頁面將跳轉至 redirect_uri/?code=CODE&state=STATE。

code說明 : code作為換取access_token的票據,每次用戶授權帶上的code將不一樣,code只能使用一次,5分鍾未被使用自動過期。

 

 第二步:通過code換取網頁授權access_token

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

  請注意,這里通過code換取的是一個特殊的網頁授權access_token,與基礎支持(素材管理等操作)中的access_token(該access_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 網頁授權接口調用憑證,注意:此access_token與基礎支持的access_token不同
openid 用戶的唯一標識
lang 返回國家地區語言版本,zh_CN 簡體,zh_TW 繁體,en 英語

 

3.代碼實現

WeixinAuthController代碼

package cn.qlq.controller.weixin;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;

import cn.qlq.utils.HttpUtils;
import cn.qlq.utils.weixin.WeixinConstants;

@Controller
@RequestMapping("weixin/auth")
public class WeixinAuthController {

    /**
     * 首頁,跳轉到index.html,index.html有一個連接會訪問下面的login方法
     * 
     * @return
     */
    @RequestMapping("/index")
    public String index() {
        return "weixinauth/index";
    }

    /**
     * (一)微信授權:重定向到授權頁面
     * 
     * @return
     * @throws UnsupportedEncodingException
     */
    @RequestMapping("/login")
    public String authorize() throws UnsupportedEncodingException {
        // 回調地址必須在公網可以訪問
        String recirectUrl = URLEncoder.encode("http://6965ee39.ngrok.io/weixin/auth/calback.html", "UTF-8");

        // 授權地址
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";
        url = url.replace("APPID", WeixinConstants.APPID).replace("REDIRECT_URI", recirectUrl);

        // 參數替換之后重定向到授權地址
        return "redirect:" + url;
    }

    /**
     * (二)用戶同意授權; (三)微信會自動重定向到配置的URL並由SpringMVC分配到該方法並攜帶參數code和state用於換取access_token和openid;
     * (四) 用access_token和openid獲取用戶信息(五)如果有必要可以進行登錄,兩種:第一種是直接拿微信號登錄;第二種是根據openid和nickname獲取賬號進行登錄
     * 
     * @param code
     * @param state
     * @return
     * @throws UnsupportedEncodingException
     */
    @RequestMapping("/calback")
    @ResponseBody
    public String calback(String code, String state) throws UnsupportedEncodingException {
        // 獲取access_token和openid
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
        url = url.replace("APPID", WeixinConstants.APPID).replace("SECRET", WeixinConstants.APP_SECRET).replace("CODE",
                code);
        String doGet = HttpUtils.doGet(url, null);
        
        if (StringUtils.isNotBlank(doGet)) {
            JSONObject parseObject = JSONObject.parseObject(doGet);
            System.out.println(parseObject);

            // 獲取兩個參數之后獲取用戶信息
            String accessToken = parseObject.getString("access_token");
            String openid = parseObject.getString("openid");
            String getUserInfoURL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
            getUserInfoURL = getUserInfoURL.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openid);
            String doGet2 = HttpUtils.doGet(getUserInfoURL, null);

            // 可以用獲取到的用戶信息進行兩種方式的登錄
            System.out.println(doGet2);
            
            return doGet2;
        }

        return "";
    }
}

 

index.html:

<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" contexnt="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body style="font-size: 40px; text-align: center;">
    <a href="/weixin/auth/login.html">微信授權登錄</a>
</body>
</html>

 

解釋:<meta name="viewport" content="width=device-width, initial-scale=1.0" /> 是讓頁面自適應手機寬度。

 

測試:

(1)從PC端訪問頁面如下:

到主頁

 

點擊微信授權登錄:

 

 (2)手機端微信內打開如下:(手機自帶的瀏覽器打開效果同上面)

到主頁:

 

點擊微信授權登錄:

 

 4. 基於微信開放平台進行登錄

  微信公眾平台主要為公眾號服務,主要用於微信公眾號二次開發;微信開放平台支持web應用、移動應該、公眾號整合等。

  到微信開放平台注冊賬號之后並認證之后創建應用(目的是為了獲取獲取AppID和APPSecret),個人無法注冊測試賬號,所以無法測試,這里只是記錄接口文檔,由於步驟與上面大體一致,有需要的時候改一下就好。

  接下來用APPID和APPSecret獲取用戶信息的步驟基本上與上面公眾號一樣。

  微信開放平台網站:https://open.weixin.qq.com/

 

步驟也是如下:

第一步:請求 CODE

  第三方使用網站應用授權登錄前請注意已獲取相應網頁授權作用域(scope=snsapi_login),則可以通過在PC端打開以下鏈接:

  https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect 

  若提示“該鏈接無法訪問”,請檢查參數是否填寫錯誤,如redirect_uri的域名與審核時填寫的授權域名不一致或scope不為snsapi_login。

參數說明:

參數 是否必須 說明
appid 應用唯一標識
redirect_uri 請使用urlEncode對鏈接進行處理
response_type 填code
scope 應用授權作用域,擁有多個作用域用逗號(,)分隔,網頁應用目前僅填寫snsapi_login即
state 用於保持請求和回調的狀態,授權請求后原樣帶回給第三方。該參數可用於防止csrf攻擊(跨站請求偽造攻擊),建議第三方帶上該參數,可設置為簡單的隨機數加session進行校驗

 

用戶允許授權后,將會重定向到redirect_uri的網址上,並且帶上code和state參數(同上面公眾號一樣)

redirect_uri?code=CODE&state=STATE

 

若用戶禁止授權,則重定向后不會帶上code參數,僅會帶上state參數

redirect_uri?state=STATE

 

第二步:通過 code 獲取 access_token

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

參數說明:

參數 是否必須 說明
appid 應用唯一標識,在微信開放平台提交應用審核通過后獲得
secret 應用密鑰AppSecret,在微信開放平台提交應用審核通過后獲得
code 填寫第一步獲取的code參數
grant_type 填authorization_code

正確的返回:

{ 
"access_token":"ACCESS_TOKEN", 
"expires_in":7200, 
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID", 
"scope":"SCOPE",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}

 

第三步:通過access_token調用接口(可以跳過,說明步驟)

  獲取access_token后,進行接口調用,有以下前提:

1. access_token有效且未超時;
2. 微信用戶已授權給第三方應用帳號相應接口作用域(scope)。

 

對於接口作用域(scope),能調用的接口有以下:

授權作用域(scope) 接口 接口說明
snsapi_base /sns/oauth2/access_token 通過code換取access_token、refresh_token和已授權scope
snsapi_base /sns/oauth2/refresh_token 刷新或續期access_token使用
snsapi_base /sns/auth 檢查access_token有效性
snsapi_userinfo /sns/userinfo 獲取用戶個人信息

 

第四步:獲取用戶個人信息(UnionID 機制)

  此接口用於獲取用戶個人信息。開發者可通過 OpenID 來獲取用戶基本信息。特別需要注意的是,如果開發者擁有多個移動應用、網站應用和公眾帳號,可通過獲取用戶基本信息中的 unionid 來區分用戶的唯一性,因為只要是同一個微信開放平台帳號下的移動應用、網站應用和公眾帳號,用戶的 unionid 是唯一的。換句話說,同一用戶,對同一個微信開放平台下的不同應用,unionid 是相同的。請注意,在用戶修改微信頭像后,舊的微信頭像 URL 將會失效,因此開發者應該自己在獲取用戶信息后,將頭像圖片保存下來,避免微信頭像 URL 失效后的異常情況。

接口地址:

  https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID

參數說明:

參數 是否必須 說明
access_token 調用憑證
openid 普通用戶的標識,對當前開發者帳號唯一
lang 國家地區語言版本,zh_CN 簡體,zh_TW 繁體,en 英語,默認為zh-CN

正確的返回:

{
"openid":"OPENID",
"nickname":"NICKNAME",
"sex":1,
"province":"PROVINCE",
"city":"CITY",
"country":"COUNTRY",
"headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/0",
"privilege":[
"PRIVILEGE1",
"PRIVILEGE2"
],
"unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL"

}

參數解釋:

參數 說明
openid 普通用戶的標識,對當前開發者帳號唯一
nickname 普通用戶昵稱
sex 普通用戶性別,1為男性,2為女性
province 普通用戶個人資料填寫的省份
city 普通用戶個人資料填寫的城市
country 國家,如中國為CN
headimgurl 用戶頭像,最后一個數值代表正方形頭像大小(有0、46、64、96、132數值可選,0代表640*640正方形頭像),用戶沒有頭像時該項為空
privilege 用戶特權信息,json數組,如微信沃卡用戶為(chinaunicom)
unionid 用戶統一標識。針對一個微信開放平台帳號下的應用,同一用戶的unionid是唯一的。

 

建議:

開發者最好保存用戶unionID信息,以便以后在不同應用中進行用戶信息互通。

unionID是用戶統一標識。統一微信開放平台下面統一用戶的unionID唯一,而且公眾號如果綁定微信開放平台之后,公眾號接口獲取的信息也會加上unionID。

 

調用頻率限制

接口名 頻率限制
通過code換取access_token 1萬/分鍾
刷新access_token 5萬/分鍾
獲取用戶基本信息 5萬/分鍾

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM