1. 程式人生 > >微信小程式授權登入獲取使用者資訊詳解

微信小程式授權登入獲取使用者資訊詳解

今天來說一下微信小程式的授權登入獲取使用者資訊,首先我們看微信提供的小程式開發文件: https://blog.csdn.net/qq_41971087/article/details/82466647 微信登入的流程和步驟: 這裡寫圖片描述 步驟:(個人): 第一步:微信小程式呼叫login和getUserInfo(),拿到code和encryptedData,iv,傳入到後臺進行業務處理 第二步:拿到code呼叫登入憑證校驗介面去獲取使用者,openid和session_key 第三步:獲取到session_key和encryptedData,iv去進行AES解密,解密成功後就可以拿到使用者資訊

頁面中的程式碼:

<view class="userinfo">
   <button wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo" 
   style="border:0px solid red;background-color:#fff;width:330rpx;" plain='true'>
     <image src="/images/user.png"  style="width:200rpx;height:200rpx;"/>
<view>請點選頭像登入</view> </button> </view>

js:

 getUserInfo: function (e) {
    console.log(5);
    console.log(e)
    if (e.detail.userInfo) {
      app.globalData.userInfo = e.detail.userInfo
      this.setData({
        userInfo: e.detail.userInfo,
        hasUserInfo: true
}) } else { this.openSetting(); } }, login: function () { console.log(111) var that = this var thist = this; // if (typeof success == "function") { // console.log(6); // console.log('success'); // this.data.getUserInfoSuccess = success // } wx.login({ success: function (res) { var code = res.code; console.log(code); wx.getUserInfo({ success: function (res) { console.log(res); wx.request({ url: app.server.hostUrl + '/api/auth/login_by_weixin.do',//自己的服務介面地址,這裡是去拿到code去後臺進行業務處理,呼叫微信介面拿到使用者openid和憑證,在解密拿到使用者資料 method: 'post', header: { 'content-type': 'application/x-www-form-urlencoded' }, data: { encryptedData: res.encryptedData, iv: res.iv, code: code }, success: function (data) { wx.setStorage({ key: "userif", data: data.data.userinfo }) console.info(data); //4.解密成功後 獲取自己伺服器返回的結果 if (data.data.code == 1) { var userInfo_ = data.data.userinfo; console.log(7); app.globalData.userInfo = userInfo_ that.setData({ getUserInfoFail: false, userInf: userInfo_, hasUserInfo: true }) thist.setData({ datas: userInfo_, index: 1 }) console.log(userInfo_) that.onLoad(); } else { console.log('解密失敗') } }, fail: function () { console.log('系統錯誤') } }) //平臺登入 }, fail: function (res) { console.log(8); console.log(res); that.setData({ getUserInfoFail: true }) } }) } }) }, //跳轉設定頁面授權 openSetting: function () { var that = this if (wx.openSetting) { wx.openSetting({ success: function (res) { console.log(9); //嘗試再次登入 that.login() } }) } else { console.log(10); wx.showModal({ title: '授權提示', content: '小程式需要您的微信授權才能使用哦~ 錯過授權頁面的處理方法:刪除小程式->重新搜尋進入->點選授權按鈕' }) } }

JAVA後臺程式碼Controller層:

 /**
     *微信登入
     * @param code 憑證
     * @param encryptedData 使用者資料
     * @param iv 使用者資料
     * @param request request作用域:
     * @return map
     */
    @RequestMapping("/login_by_weixin")
    @ResponseBody
    public Map loginByWeixin(String code, String encryptedData, String iv, HttpServletRequest request)
    {
            Map<String,Object> map  =new HashMap<String, Object>();

            String sendGet=userService.loginByWeixin(code); //根據code去呼叫介面獲取使用者openid和session_key

            JSONObject json = JSONObject.fromObject(sendGet);
            System.out.println("返回過來的json資料:"+json.toString());
            String sessionkey=json.get("session_key").toString(); //會話祕鑰
            String openid=json.get("openid").toString(); //使用者唯一標識
            try{
            //拿到使用者session_key和使用者敏感資料進行解密,拿到使用者資訊。
             String decrypts=AesCbcUtil.decrypt(encryptedData,sessionkey,iv,"utf-8");//解密
               JSONObject jsons = JSONObject.fromObject(decrypts);
                   String nickName=jsons.get("nickName").toString(); //使用者暱稱
                   String jsonsds=jsonsd.get("avatarUrl").toString(); //使用者頭像
                    jsons.get("avatarUrl").toString(); //頭像
                    jsons.get("gender").toString();//性別 
                   jsons.get("unionid").toString(); //unionid
                   jsons.get("city").toString(); //城市
                  jsons.get("province").toString();//省份
                   jsons.get("country").toString(); //國家
            }catch (Exception e) {
             e.printStackTrace();
            }
    }

這裡拿到使用者資訊自己去做處理,儲存到資料庫中,這裡我就不編寫了 userServiceImpl.java:

 /**
     *微信登入業務實現類:
     * @param openid 使用者id
     * @return User
     */
     @Override
    public String loginByWeixin(String code, String encryptedData, String iv) {
        Map<String, Object> map = new HashMap<String, Object>();
        //傳送    https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code 獲取使用者的openid和session_key
        //注意這個是 WeChatTool.wxspAppid 是微信小程式的appid 從微信小程式後臺獲取 WeChatTool.wxspSecret 這個也一樣,我這裡是用了常量來進行儲存方便多次使用
        String params = "appid=" + WeChatTool.wxspAppid + "&secret=" + WeChatTool.wxspSecret + "&js_code=" + code + "&grant_type=authorization_code";
        String sendGet = Httprequests.sendGet(WeChatTool.url, params); //發起請求拿到key和openid
        return sendGet;
    }

Httprequests.java(傳送網路請求的工具類)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.servlet.http.HttpServletRequest;
/**
 * <p>User: xxx
 * <p>Date: 14-1-28
 * <p>Version: 1.0
 * 描述: http發起請求:
 */
public class Httprequests {


    //測試,傳送請求是否成功:
    public static void main(String[] aegs) {
        String string = Httprequests.sendGet("http://v.qq.com/x/cover/kvehb7okfxqstmc.html?vid=e01957zem6o","");
        System.out.print(string);
    }

    //傳送GET請求:
    public static String  sendGet (String url,String param) {
        String result ="";
        BufferedReader in  =null;
        try {
            String urlNameString = url +"?" +param;
            System.out.println("傳送的連結請求:"+urlNameString);
            URL reaurl = new URL(urlNameString);

            URLConnection connection  = reaurl.openConnection();

            //設定通用
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");

            //建立實際的連線
            connection.connect();

            Map<String, List<String>> map = connection.getHeaderFields();
            //定義 BufferedReader輸入流來讀取URL的響應
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("傳送GET請求出現異常!" + e);
            e.printStackTrace();
        }
        // 使用finally塊來關閉輸入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result;
    }


    /**
     * 向指定 URL 傳送POST方法的請求
     * @param url 傳送請求的 URL
     * @param param 引數
     * @return String 所代表遠端資源的響應結果
     */
    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 開啟和URL之間的連線
            URLConnection conn = realUrl.openConnection();
            // 設定通用的請求屬性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 傳送POST請求必須設定如下兩行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 獲取URLConnection物件對應的輸出流
            out = new PrintWriter(conn.getOutputStream());

            // 傳送請求引數
            out.print(param);
            // flush輸出流的緩衝
            out.flush();
            // 定義BufferedReader輸入流來讀取URL的響應
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("傳送 POST 請求出現異常!"+e);
            e.printStackTrace();
        }
        //使用finally塊來關閉輸出流、輸入流
        finally{
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            }
            catch(IOException ex){
                ex.printStackTrace();
            }
        }
        return result;
    }

}

AesCbcUtil.java(拿使用者的session_key和微信小程式傳過來的iv和encryptedData進行解密的工具類)

import java.io.UnsupportedEncodingException;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidParameterSpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.management.openmbean.InvalidKeyException;
import org.apache.commons.codec.binary.Base64;
/**
 * <p>User: qrn
 * <p>Date: 14-1-28
 * <p>Version: 1.0
 * 描述: 解密
 */
public class AesCbcUtil {



    /**
     * AES解密
     *
     * @param encryptedData  包括敏感資料在內的完整使用者資訊的加密資料,
     * @param key    祕鑰
     * @param iv     加密演算法的初始向量,
     * @param encodingFormat 解密後的結果需要進行的編碼
     * @return String
     * @see  Exception
     */
    public static String decrypt(String encryptedData,String key, String iv, String encodingFormat) throws Exception {
//        initialize();

        //被加密的資料
        byte[] dataByte = Base64.decodeBase64(data);
        //加密祕鑰
        byte[] keyByte = Base64.decodeBase64(key);
        //偏移量
        byte[] ivByte = Base64.decodeBase64(iv);


        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

            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) {
                String result = new String(resultByte, encodingFormat);
                return result;
            }
            return null;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidParameterSpecException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidAlgorithmParameterException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

}

如果上面的執行沒有錯誤的話,就可以拿到使用者的資訊,這個程式碼應該是不會出問題,如果有問題請下發評論我會及時的回答,其實微信的開發文件中這些東西以經寫的很清楚,希望微信開發的朋友可以認真仔細的觀看微信文件,希望這篇文字對大家有用,謝謝