This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.

Introduction to the

There are two ways to scan wechat web pages for login authorization:

  • The first type: Based on the wechat public account, obtain the qr code for login separately, and then scan the code for login. The program controls the jump logic, such as CSDN:

  • Second: Based on the wechat open platform, jump to the wechat TWO-DIMENSIONAL code page for scanning code login and redirect to the success page, such as Youdao Note:

Note:This paper records the first way, just through the wechat test public account can complete the test, that is, everyone can run completely locally; The second requires a developer account with a certified qualification, which will be recorded later.

A complete local operating environment is available

Intranet penetration => Generate the extranet domain name of the specified local port mapping

Portal:Details on the use of Intranet penetration tool Natapp Modify configuration file after domain name generation:

Register and configure wechat test public account

  1. Registered address: Wechat public platform test account application, scan code to log in, and follow the test number

  1. Get the test number AppID and AppSecret

3. Interface configuration modification (The background signature verification method is called back. You need to start the background during configuration)4. Configure the authorized domain name for obtaining wechat user information

process

Text briefly

  1. Page click to obtain the wechat login TWO-DIMENSIONAL code button
  2. The background uses appID and appsecret as parameters to call wechat API to obtain access_token
  3. Call wechat API with access_token as parameter to obtain local wechat login QR code ticket, and pass the random string parameter scene_str. This participation can be used by the program to verify whether the code scanning is successful
  4. If the QR code is successfully obtained through ticket, the page is displayed. At the same time, the foreground starts js scheduled tasks (which can be optimized into background notifications), and monitors whether the code scanning is successful
  5. The user successfully scanned the code on wechat
  6. Wechat server callback Local server signature verification interface verifies signature and callback processing
  7. The callback process determines that the sweep was successful (you can also verify this with attention) and that the database or cache inserts a record of the local sweep success
  8. The periodic task in the foreground obtains the code sweep success record or the background proactively notifies it to process the code sweep success

code

1. Obtain the wechat QR code and start the JS scheduled task

The front desk HTML

<h1>Wechat code scanning login method 1</h1>
    <button onclick="getQrCode()" style="width: 100px; height: 50px;">Get the QR code</button>
    <br>
    <img src="" id="qrCodeImgId"  style="width: 300px; height: 300px; display: none">
<hr>
Copy the code

The front desk js

/ / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = WeChat scan code means a = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
    // Stores the QR code to verify whether the scan is successful
    var sceneStr;
    var t;
    // Get the login qr code
    function getQrCode(){
        $.get('qrCodeFirstLogin/getQrCode'.function (data) {
            console.log("=============getQrCode=======================");
            console.log(data);
            if(data.code == 200){
                sceneStr = data.data.sceneStr;
                // Obtain the qr code
                $('#qrCodeImgId').attr('src'."https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket="+data.data.ticket);
                $('#qrCodeImgId').show();
                // Check whether the scheduled task is scanning codes successfully
                t = window.setInterval(getOpenId,3000);
            }else{ alert(data.msg); }}); }Copy the code

The ticket interface with a QR code is obtained from the background

    /** * get accessToken *@return* /
    public String getAccessToken(a){
        String accessToken = null;
        String getTokenUrl = wxConfig.getTokenUrl().replace("APPID", wxConfig.getAppId()).replace("SECRET", wxConfig.getAppSecret());
        String result = HttpClientUtil.doGet(getTokenUrl);
        JSONObject jsonObject = JSONObject.parseObject(result);
        accessToken = jsonObject.getString("access_token");
        return accessToken ;
    }
    /** * Obtain the login qr code *@return* /
    @GetMapping("/getQrCode")
    private ResultJson getQrCode(a){
        try {
            // Get token developers
            String accessToken =getAccessToken();
            String getQrCodeUrl = wxConfig.getQrCodeUrl().replace("TOKEN", accessToken);
            // Generate a qr code with parameters scene_str
            String sceneStr = CodeLoginUtil.getRandomString(8);
            String json="{\"expire_seconds\": 604800, \"action_name\": \"QR_STR_SCENE\"" +", \"action_info\": {\"scene\": {\"scene_str\": \""+sceneStr+"\"}}}";
            String result  = HttpClientUtil.doPostJson(getQrCodeUrl,json);
            JSONObject jsonObject = JSONObject.parseObject(result);
            jsonObject.put("sceneStr",sceneStr);
            return ResultJson.ok(jsonObject);
        } catch (Exception e) {
            e.printStackTrace();
            returnResultJson.error(e.getMessage()); }}Copy the code

2. Signature verification and callback processing

/** * Verify signature *@param request
     * @return
     * @throws Exception
     */
    @RequestMapping("/checkSign")
    public String checkSign ( HttpServletRequest request) throws Exception {
        log.info("===========>checkSign");
        // Get wechat request parameters
        String signature = request.getParameter ("signature");
        String timestamp = request.getParameter ("timestamp");
        String nonce = request.getParameter ("nonce");
        String echostr = request.getParameter ("echostr");
        // Sort parameters. The token is replaced by the token you actually wrote
        String [] params = new String [] {timestamp,nonce,"123456"}; Arrays.sort (params) ;/ / stitching
        String paramstr = params[0] + params[1] + params[2];/ / encryption
        // Get the shAL algorithm encapsulation class
        MessageDigest Sha1Dtgest = MessageDigest.getInstance("SHA-1");// Encrypt
        byte [] digestResult = Sha1Dtgest.digest(paramstr.getBytes ("UTF-8"));
        // get the encryption result
        String mysignature = CodeLoginUtil.bytes2HexString(digestResult);
        mysignature=mysignature.toLowerCase(Locale.ROOT);
        // Is this correct
        boolean signsuccess = mysignature.equals(signature);
        // Logical processing
        if(signsuccess && echostr! =null) {
            //peizhi token
            return echostr  ;// If not, return a failure message.
        }else{
            JSONObject jsonObject = callback(request);
            returnjsonObject.toJSONString(); }}/** * callback method *@param request
     * @return
     * @throws Exception
     */
    public JSONObject callback(HttpServletRequest request) throws Exception{
        log.info("===========>callback");
        // There is corresponding information in the request
        WxMpXmlMessage message= WxMpXmlMessage.fromXml(request.getInputStream());// Get the message flow and parse the XML
        String messageType=message.getMsgType();								// Message type
        String messageEvent=message.getEvent();								    // Message event
        // openid
        String fromUser=message.getFromUser();									// Sender account
        String touser=message.getToUser();										// Developer wechat id
        String text=message.getContent();										// Text message text content
        // Special parameters passed when generating the QR code
        String eventKey=message.getEventKey();									// Code parameters

        String uuid="";															// Obtain the UUID from the two-dimensional code parameters. The UUID can be used to transmit data through the websocket front end
        String userid="";

        //if query
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code"."200");
        if(messageType.equals("event")){
             jsonObject = null;
            // Query user information from the openID database => jsonObject
            if(messageEvent.equals("SCAN")) {// Scan the qr code
                //return "welcome back ";
            }
            if(messageEvent.equals("subscribe")) {/ / concern
                //return "Thank you for your attention ";
            }
            // There is no such user
            if(jsonObject==null) {// Pull user information from wechat
                String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" +getAccessToken() +
                        "&openid=" + fromUser +
                        "&lang=zh_CN";
                String result = HttpClientUtil.doGet(url);
                jsonObject = JSONObject.parseObject(result);
                /** * user information processing.... * /
            }
            // The code is scanned successfully and stored in cache
            loginMap.put(eventKey,new CodeLoginKey(eventKey,fromUser));
            return jsonObject;
        }
        return jsonObject;
        / / the log. The info (" message types: {}, news events: {}, the sender account: {}, the receiver WeChat: {}, a text message: {}, qr code parameters: {} ", messageType, messageEvent, fromUser, touser, text, eventKey);
    }
Copy the code

3. The user information is obtained successfully. Cancel the scheduled task

Js periodic task monitoring

    // If the scan succeeds and user openId is obtained => Prepare for obtaining user information
    function getOpenId() {
        $.get("qrCodeFirstLogin/getOpenId", {"eventKey":sceneStr
        },function (data) {
            if(data.code == 200) {console.log("========getOpenId==========");
                console.log(data.data);
                window.clearInterval(t);
                alert("Login successful openId:"+data.data.openId);
                /** * 1. Bind the account by scanning the code for the first time. 2}}); }Copy the code

Background authentication interface

    /** * Obtain user openId according to qr code identifier => Obtain user information *@param eventKey
     * @return* /
    @RequestMapping("getOpenId")
    public ResultJson getOpenId(String eventKey){
        if(loginMap.get(eventKey) == null) {return ResultJson.error("No code scan success!"); } CodeLoginKey codeLoginKey = loginMap.get(eventKey); loginMap.remove(eventKey);return ResultJson.ok(codeLoginKey);
    }
Copy the code

The results demonstrate

Get the QR code

Sweep code success

The source code

Portal: wechat PC scan code login