1. 程式人生 > >微信網頁授權—驗證伺服器配置

微信網頁授權—驗證伺服器配置

第一步,成為開發者

1.填寫伺服器配置

登入微信公眾平臺官網後,在公眾平臺官網的開發-基本設定頁面,勾選協議成為開發者,點選“修改配置”按鈕,填寫伺服器地址(URL)、Token和EncodingAESKey,其中URL是開發者用來接收微信訊息和事件的介面URL。Token可由開發者可以任意填寫,用作生成簽名(該Token會和介面URL中包含的Token進行比對,從而驗證安全性)。EncodingAESKey由開發者手動填寫或隨機生成,將用作訊息體加解密金鑰。
這裡寫圖片描述
Url伺服器地址是微信回撥地址,必須以 http://或https://開頭,埠號必須為80或443。
Token令牌由使用者自己定義,數字或字母,長度為3~32字元。
EncodingAESKey隨機生成即可。
加密方式可以選明文模式和安全模式。

2.驗證伺服器配置
點選啟用後,微信伺服器將傳送GET請求到你的伺服器地址URL上,並攜帶四個引數:signature 微信加密簽名(signature結合了開發者填寫的token引數和請求中的timestamp引數、nonce引數),timestamp 時間戳,nonce 隨機數,echostr 隨機字串。
伺服器需要接受上面四個引數,並進行校驗,若確認此次GET請求來自微信伺服器,請原樣返回echostr引數內容,則接入生效,成為開發者成功,否則接入失敗。
校驗流程為:
1)將token、timestamp、nonce三個引數進行字典序排序
2)將三個引數字串拼接成一個字串進行sha1加密
3)開發者獲得加密後的字串可與signature對比,標識該請求來源於微信
校驗程式碼(java)

package com.sh.inter;

import java.io.IOException;
import java.util.Arrays;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sh.util.SHA1;

/**
 * 開發者通過檢驗signature對請求進行校驗(下面有校驗方式)。若確認此次GET請求來自微信伺服器,請原樣返回echostr引數內容,則接入生效,成為開發者成功,否則接入失敗。
 * 加密/校驗流程如下:
 * 1)將token、timestamp、nonce三個引數進行字典序排序
 * 2)將三個引數字串拼接成一個字串進行sha1加密
 * 3)開發者獲得加密後的字串可與signature對比,標識該請求來源於微信
 * @author
季小沫的故事 */
public class AccessWet extends HttpServlet { private static final long serialVersionUID = 1L; //使用者自定義TOKEN public static String TOKEN = "micomo";//使用者在微信伺服器配置填寫的token public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 微信加密簽名 String signature = request.getParameter("signature"); // 隨機字串 String echostr = request.getParameter("echostr"); // 時間戳 String timestamp = request.getParameter("timestamp"); // 隨機數 String nonce = request.getParameter("nonce"); // 字典序排序 String[] str = { TOKEN, timestamp, nonce }; Arrays.sort(str); String bigStr = str[0] + str[1] + str[2]; // SHA1加密 String digest = new SHA1().getDigestOfString(bigStr.getBytes()).toLowerCase(); // 確認請求來至微信 if (digest.equals(signature)) { response.getWriter().append(echostr); } } }

SHA1加密程式碼

package com.sh.util;
/**
 * 
 * 檔名      :     WechatCallbackApi.java<br/>
 * 作者           :     songhuihui <br/>
 * 建立日期 :     2013-9-27<br/>
 * 站點 :      http://wuzhut.com<br/>
 */
public class SHA1 {
    private final int[] abcde = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 };
    // 摘要資料儲存陣列
    private int[] digestInt = new int[5];
    // 計算過程中的臨時資料儲存陣列
    private int[] tmpData = new int[80];

    // 計算sha-1摘要
    private int process_input_bytes(byte[] bytedata) {
        // 初試化常量
        System.arraycopy(abcde, 0, digestInt, 0, abcde.length);
        // 格式化輸入位元組陣列,補10及長度資料
        byte[] newbyte = byteArrayFormatData(bytedata);
        // 獲取資料摘要計算的資料單元個數
        int MCount = newbyte.length / 64;
        // 迴圈對每個資料單元進行摘要計算
        for (int pos = 0; pos < MCount; pos++) {
            // 將每個單元的資料轉換成16個整型資料,並儲存到tmpData的前16個數組元素中
            for (int j = 0; j < 16; j++) {
                tmpData[j] = byteArrayToInt(newbyte, (pos * 64) + (j * 4));
            }
            // 摘要計算函式
            encrypt();
        }
        return 20;
    }

    // 格式化輸入位元組陣列格式
    private byte[] byteArrayFormatData(byte[] bytedata) {
        // 補0數量
        int zeros = 0;
        // 補位後總位數
        int size = 0;
        // 原始資料長度
        int n = bytedata.length;
        // 模64後的剩餘位數
        int m = n % 64;
        // 計算新增0的個數以及新增10後的總長度
        if (m < 56) {
            zeros = 55 - m;
            size = n - m + 64;
        } else if (m == 56) {
            zeros = 63;
            size = n + 8 + 64;
        } else {
            zeros = 63 - m + 56;
            size = (n + 64) - m + 64;
        }
        // 補位後生成的新陣列內容
        byte[] newbyte = new byte[size];
        // 複製陣列的前面部分
        System.arraycopy(bytedata, 0, newbyte, 0, n);
        // 獲得陣列Append資料元素的位置
        int l = n;
        // 補1操作
        newbyte[l++] = (byte) 0x80;
        // 補0操作
        for (int i = 0; i < zeros; i++) {
            newbyte[l++] = (byte) 0x00;
        }
        // 計算資料長度,補資料長度位共8位元組,長整型
        long N = (long) n * 8;
        byte h8 = (byte) (N & 0xFF);
        byte h7 = (byte) ((N >> 8) & 0xFF);
        byte h6 = (byte) ((N >> 16) & 0xFF);
        byte h5 = (byte) ((N >> 24) & 0xFF);
        byte h4 = (byte) ((N >> 32) & 0xFF);
        byte h3 = (byte) ((N >> 40) & 0xFF);
        byte h2 = (byte) ((N >> 48) & 0xFF);
        byte h1 = (byte) (N >> 56);
        newbyte[l++] = h1;
        newbyte[l++] = h2;
        newbyte[l++] = h3;
        newbyte[l++] = h4;
        newbyte[l++] = h5;
        newbyte[l++] = h6;
        newbyte[l++] = h7;
        newbyte[l++] = h8;
        return newbyte;
    }

    private int f1(int x, int y, int z) {
        return (x & y) | (~x & z);
    }

    private int f2(int x, int y, int z) {
        return x ^ y ^ z;
    }

    private int f3(int x, int y, int z) {
        return (x & y) | (x & z) | (y & z);
    }

    private int f4(int x, int y) {
        return (x << y) | x >>> (32 - y);
    }

    // 單元摘要計算函式
    private void encrypt() {
        for (int i = 16; i <= 79; i++) {
            tmpData[i] = f4(tmpData[i - 3] ^ tmpData[i - 8] ^ tmpData[i - 14]
                    ^ tmpData[i - 16], 1);
        }
        int[] tmpabcde = new int[5];
        for (int i1 = 0; i1 < tmpabcde.length; i1++) {
            tmpabcde[i1] = digestInt[i1];
        }
        for (int j = 0; j <= 19; j++) {
            int tmp = f4(tmpabcde[0], 5)
                    + f1(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4]
                    + tmpData[j] + 0x5a827999;
            tmpabcde[4] = tmpabcde[3];
            tmpabcde[3] = tmpabcde[2];
            tmpabcde[2] = f4(tmpabcde[1], 30);
            tmpabcde[1] = tmpabcde[0];
            tmpabcde[0] = tmp;
        }
        for (int k = 20; k <= 39; k++) {
            int tmp = f4(tmpabcde[0], 5)
                    + f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4]
                    + tmpData[k] + 0x6ed9eba1;
            tmpabcde[4] = tmpabcde[3];
            tmpabcde[3] = tmpabcde[2];
            tmpabcde[2] = f4(tmpabcde[1], 30);
            tmpabcde[1] = tmpabcde[0];
            tmpabcde[0] = tmp;
        }
        for (int l = 40; l <= 59; l++) {
            int tmp = f4(tmpabcde[0], 5)
                    + f3(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4]
                    + tmpData[l] + 0x8f1bbcdc;
            tmpabcde[4] = tmpabcde[3];
            tmpabcde[3] = tmpabcde[2];
            tmpabcde[2] = f4(tmpabcde[1], 30);
            tmpabcde[1] = tmpabcde[0];
            tmpabcde[0] = tmp;
        }
        for (int m = 60; m <= 79; m++) {
            int tmp = f4(tmpabcde[0], 5)
                    + f2(tmpabcde[1], tmpabcde[2], tmpabcde[3]) + tmpabcde[4]
                    + tmpData[m] + 0xca62c1d6;
            tmpabcde[4] = tmpabcde[3];
            tmpabcde[3] = tmpabcde[2];
            tmpabcde[2] = f4(tmpabcde[1], 30);
            tmpabcde[1] = tmpabcde[0];
            tmpabcde[0] = tmp;
        }
        for (int i2 = 0; i2 < tmpabcde.length; i2++) {
            digestInt[i2] = digestInt[i2] + tmpabcde[i2];
        }
        for (int n = 0; n < tmpData.length; n++) {
            tmpData[n] = 0;
        }
    }

    // 4位元組陣列轉換為整數
    private int byteArrayToInt(byte[] bytedata, int i) {
        return ((bytedata[i] & 0xff) << 24) | ((bytedata[i + 1] & 0xff) << 16)
                | ((bytedata[i + 2] & 0xff) << 8) | (bytedata[i + 3] & 0xff);
    }

    // 整數轉換為4位元組陣列
    private void intToByteArray(int intValue, byte[] byteData, int i) {
        byteData[i] = (byte) (intValue >>> 24);
        byteData[i + 1] = (byte) (intValue >>> 16);
        byteData[i + 2] = (byte) (intValue >>> 8);
        byteData[i + 3] = (byte) intValue;
    }

    // 將位元組轉換為十六進位制字串
    private static String byteToHexString(byte ib) {
        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
                'B', 'C', 'D', 'E', 'F' };
        char[] ob = new char[2];
        ob[0] = Digit[(ib >>> 4) & 0X0F];
        ob[1] = Digit[ib & 0X0F];
        String s = new String(ob);
        return s;
    }

    // 將位元組陣列轉換為十六進位制字串
    private static String byteArrayToHexString(byte[] bytearray) {
        String strDigest = "";
        for (int i = 0; i < bytearray.length; i++) {
            strDigest += byteToHexString(bytearray[i]);
        }
        return strDigest;
    }

    // 計算sha-1摘要,返回相應的位元組陣列
    public byte[] getDigestOfBytes(byte[] byteData) {
        process_input_bytes(byteData);
        byte[] digest = new byte[20];
        for (int i = 0; i < digestInt.length; i++) {
            intToByteArray(digestInt[i], digest, i * 4);
        }
        return digest;
    }

    // 計算sha-1摘要,返回相應的十六進位制字串
    public String getDigestOfString(byte[] byteData) {
        return byteArrayToHexString(getDigestOfBytes(byteData));
    }

    public static void main(String[] args) {
        String data = "123456";
        System.out.println(data);
        String digest = new SHA1().getDigestOfString(data.getBytes());
        System.out.println(digest);

        // System.out.println( ToMD5.convertSHA1(data).toUpperCase());
    }
}

精簡版SHA1類

package com.sh.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class SHA1 {

    public static String sha1(String input) throws NoSuchAlgorithmException {

        MessageDigest mDigest = MessageDigest.getInstance("SHA1");
        byte[] result = mDigest.digest(input.getBytes());
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < result.length; i++) {
            sb.append(Integer.toString((result[i] & 0xff) + 0x100, 16).substring(1));
        }
        return sb.toString();
    }
}

到此,完成伺服器配置,並且成功驗證,成為開發者。
根據相關義務需求,呼叫微信開放介面。
相關微信開發文件

相關推薦

網頁授權驗證伺服器配置

第一步,成為開發者 1.填寫伺服器配置 登入微信公眾平臺官網後,在公眾平臺官網的開發-基本設定頁面,勾選協議成為開發者,點選“修改配置”按鈕,填寫伺服器地址(URL)、Token和EncodingAESKey,其中URL是開發者用來接收微信訊息和事件的介面U

伺服器配置的一點點經驗(內含:驗證伺服器出現token驗證失敗的處理,接收事件出現XML格式錯誤,網頁授權獲取 access token 報錯40125)

首先需要多些網上的大神 連結:https://bbs.csdn.net/topics/390991193 ; https://blog.csdn.net/sinat_22878395/article/details/69258165 ; https://blog.csdn.net/hangh

網頁授權獲取用戶息等機制

json 開發者 userinfo 技術分享 nal amp 分隔 response unionid 參考官方文檔 https://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html 1.用戶進入授權

網頁授權-公眾號支付(獲取openid、用戶息等)

blog red code rect ref true 說明 oauth2 具體細節 名詞解釋: openid 用戶唯一標識,請註意,在未關註公眾號時,用戶訪問公眾號的網頁,也會產生一個用戶和公眾號唯一的OpenID 業務功能描述:實現H

網頁授權

cde 註意 connect encode res str abc 有關 href 有關微信網頁授權 let wechat = { getCode:function(appids){ /** * 獲取微信code

【TP3.2.3】網頁授權--基類

重新 exec 進入 index.php sset AR 關註 fun func 非常好用的微信授權 基類:其他的微信權限類都可以繼承至該類: <?php namespace Wechat\Controller; use Think\Controller;

手把手實現網頁授權支付,附源代碼(VUE and thinkPHP)

nec ble 名單 ret 一次 hash 掃一掃 網頁 ada wechat github 手把手實現微信網頁授權和微信支付,附源代碼(VUE and thinkPHP) 概述 公眾號開發是痛苦的,痛苦在好多問題開發者文檔是沒有提到的,是需要你猜的. 在開發過程中翻

.netMVC企業網頁授權+註冊全局過濾器

glob for init cgi http 一個 使用 QQ == 微信網頁授權   達到效果:企業應用只能在微信中查看,在瀏覽器中打開企業頁面,顯示無權限! 原理,用session記錄用戶,如果用戶已經通過微信授權,記錄@Session["UserId"],如果用戶

解決網頁授權一個回調域名多個業務使用

ces 公眾號授權 存在 方案 安全問題 TP 公眾 處理 source 前言 我們都知道微信的網頁授權回調域名只能設置一個,但是多個業務使用同一個微信公眾號授權信息的話,就需要使用者內部進行處理了,下面給出我使用的一種簡陋的解決方案。 方法 正常流程 1: 第一步:用戶同

H5獲取網頁授權

esp lin storage {} cti 調用接口 set auth nav //判斷是否微信瀏覽器 isWeiXin: function(){   let ua = window.navigator.userAgent.toLowerCase();   retur

網頁授權報code been used, hints: [ req_id: XYv1Ha07042046 ]

web 獲取 UNC color 微信網頁授權 oauth image 授權 use 先貼上代碼: public function index() { $code = input(‘get.code‘); $tool = n

VueJs單頁應用實現網頁授權分享功能示例

在實際開發中,無論是做PC端、WebApp端還是微信公眾號等型別的專案的時候,或多或少都會涉及到微信相關的開發,最近公司專案要求實現微信網頁授權,並獲取微信使用者基本資訊的功能及微信分享的功能,現在總算完成了,但開發過程中遇到好幾個坑。廢話不多說了,開始正題。 描述點 微信相關開發知識

網頁授權——獲取code、access_token、openid,及跨域問題解決

首先在微信開發文件中有提到微信網頁授權的操作步驟: 第一步:使用者同意授權,獲取code 在確保微信公眾賬號擁有授權作用域(scope引數)的許可權的前提下(服務號獲得高階介面後,預設擁有scope引數中的snsapi_base和snsapi_userinfo),引導關注者開啟如下頁面:

網頁授權獲取code

<script> (function(){ var code = GetQueryString('code'); if(code){ alert(code) return false; }else{ shouquan(); } function shouquan(){ var redi

網頁授權失敗原因總結

1.專案中網頁授權回撥地址與微信公眾號設定的回撥地址不一樣 2.如果公眾號為服務號,沒有把MP_verify_zoOZRR6Jqi5eQA1n.txt貼上進專案裡 3.如果公眾號為服務號,專案必須要用域名訪問地址 4.如果公眾號為測試號,也不可以用ip地址做專案訪問地址,因為用ip地址訪問的話

PHP 網頁授權獲取使用者資訊

  class WxController extends Controller {     //put your code here     /**      * 微信授權相關介面

網頁授權access_token 與 基礎支援的access_token

   在此總結一下網頁授權access_token 與 微信基礎支援的access_token 的區別。 1. 網頁授權access_token  微信開放平臺的使用者掃碼登陸網站, 微信公眾號的H5頁面獲取使用者資訊, 微信小程式中的access_token均

普通js使用ajax,公眾號授權網頁授權

微信授權的整個流程: 引導使用者進入授權頁面同意授權,獲取code 通過code換取網頁授權access_token(與基礎支援中的access_token不同) 如果需要,開發者可以重新整理網頁授權access_token,避免過期 通過網頁授權access_tok

vue腳手架,公眾號授權網頁授權

如果使用者在微信客戶端中訪問第三方網頁,公眾號可以通過微信網頁授權機制,來獲取使用者基本資訊,進而實現業務邏輯。 首先我做了一個H5小專案,然後申請公眾號,然後在【自定義選單】中輸入想填寫的,公眾號選單名稱,以及頁面地址: 然後,我們在我們的前端頁面寫呼叫伺服器介面,得到授權。當然

網頁授權中遇到的兩個小問題解決

在用微信公眾號測試賬號測試時遇到兩個問題: 1、Scope 引數錯誤或沒有 Scope 許可權 2、解決1後,遇到  redirect_uri 引數錯誤   問題1是因為測試賬號在許可權表中需要設定訪問“授權回撥頁面域名”,如果沒設定的話就會返回“Scope