Inicio de sesión de terceros: inicio de sesión con código de escaneo de WeChat


Los amigos que tengan varias preguntas pueden consultar los documentos oficiales para estudiar en detalle los documentos de desarrollo de WeChat . Esta vez presentaremos el inicio de sesión del código de escaneo de WeChat que no separa el front-end y el back-end.

Proceso de desarrollo de inicio de sesión de WeChat:

  1. Solicite acceso a WeChat
  2. Generar código QR de inicio de sesión
  3. El usuario escanea el código y autoriza
  4. Llame al método de devolución de llamada
  5. Obtenga información del usuario a través del código y llévela a la página para mostrarla.

Diagrama de flujo oficial:
Insertar descripción de la imagen aquí

1. Solicite acceso a WeChat:

En primer lugar, me gustaría recordarles a todos: es muy problemático solicitar acceso a WeChat. Debido a las necesidades comerciales de la empresa, utilizo la aplicación de la empresa. Todavía no me he aplicado.

Primero vaya a la plataforma abierta WeChat https://open.weixin.qq.com

Insertar descripción de la imagen aquí
Solicite una solicitud de sitio web (solo se puede utilizar después de la aprobación)

Insertar descripción de la imagen aquí
Nota:

  1. appid y appSecret son las credenciales para llamar a la interfaz WeChat
  2. Dominio de devolución de llamada de autorización: la dirección del código QR generada al llamar a la interfaz WeChat. Después de que el usuario escanea el código y lo autoriza, será redirigido a la dirección de devolución de llamada.
  3. Debido a que la prueba se realiza en localhost, WeChat de terceros no podrá saltar si la dirección de devolución de llamada es localhost. La razón es que la red externa no puede acceder al área local. ¿Qué debo hacer? Solución: luego use la penetración de la intranet de ngrok para asignar el servicio del proyecto local a la red pública, de modo que la dirección de devolución de llamada completada durante la prueba sea el nombre de dominio de acceso. durante la penetración de la intranet.
  4. Si no conoce la penetración de la intranet, le sugiero que primero eche un vistazo al uso de la penetración de la intranet Sunny-Ngrok .

Insertar descripción de la imagen aquí

Si no conoce la penetración de la intranet, le sugiero que primero eche un vistazo al uso de la penetración de la intranet Sunny-Ngrok .

Inicie el cliente de penetración de intranet Sunny-Ngrok y primero asigne el servicio local a la red pública.

Insertar descripción de la imagen aquí

2. Configuración del entorno del proyecto:

Comencemos oficialmente la parte del código, creemos un proyecto SpringBoot e importemos el paquete Jar requerido:
Entorno: JDK1.8, SpringBoot2.3.5.RELEASE

<dependencies>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter</artifactId>
       </dependency>

       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-thymeleaf</artifactId>
       </dependency>

       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>

       <dependency>
           <groupId>org.apache.httpcomponents</groupId>
           <artifactId>httpclient</artifactId>
           <version>4.5.13</version>
       </dependency>
       
       <dependency>
           <groupId>org.json</groupId>
           <artifactId>json</artifactId>
           <version>20200518</version>
       </dependency>
</dependencies>

Archivo yaml:
debido a que estos cuatro parámetros son obligatorios, se configuran directamente en el archivo yaml y, cuando se usan, se pueden introducir directamente en la clase a través de la anotación @Value.

  1. rápido:
  2. App secreta:
  3. alcance: snsapi_login
  4. llamar de vuelta:
server:
  port: 80

spring:
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
  mvc:
    static-path-pattern: classpath:/static/

wechat:
  #微信接口的AppID:
  appid: 
  #微信接口的AppSecret:
  appsecret: 
  #应用授权作用域(网站应用目前的固定写法就是snsapi_login)
  scope: snsapi_login
  #扫码之后的回调地址:
  callBack: http://wechatlogin.free.idcfengye.com/callBack

Aquí se necesita una clase de herramienta HttpRequestUtils para iniciar solicitudes http. Puedes copiar el código directamente y usarlo.

package com.login.utils;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

/**
 * @author: libo
 * @date: 2020/11/21  20:49
 * @motto: 即使再小的帆也能远航
 */
public class HttpRequestUtils {
    
    

    private static CloseableHttpClient httpClient;

    static {
    
    
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setMaxTotal(100);
        cm.setDefaultMaxPerRoute(20);
        cm.setDefaultMaxPerRoute(50);
        httpClient = HttpClients.custom().setConnectionManager(cm).build();
    }

    public static String httpGet(String url) {
    
    
        CloseableHttpResponse response = null;
        BufferedReader in = null;
        String result = "";
        try {
    
    
            HttpGet httpGet = new HttpGet(url);
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();
            httpGet.setConfig(requestConfig);
            httpGet.setConfig(requestConfig);
            httpGet.addHeader("Content-type", "application/json; charset=utf-8");
            httpGet.setHeader("Accept", "application/json");
            response = httpClient.execute(httpGet);
            in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            StringBuffer sb = new StringBuffer("");
            String line = "";
            String NL = System.getProperty("line.separator");
            while ((line = in.readLine()) != null) {
    
    
                sb.append(line + NL);
            }
            in.close();
            result = sb.toString();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                if (null != response) {
    
    
                    response.close();
                }
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
        return result;
    }
}

3. Interfaz del controlador backend:

package com.login.controller;

import com.login.utils.HttpRequestUtils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;

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

/**
 * @author: libo
 * @date: 2020/11/21  21:32
 * @motto: 即使再小的帆也能远航
 */
@Controller
@CrossOrigin
@SuppressWarnings("unchecked")
public class weChatController {
    
    

    @Value(value = "${wechat.appid}")
    private String appid;

    @Value(value = "${wechat.appsecret}")
    private String appsecret;

    @Value(value = "${wechat.scope}")
    private String scope;

    @Value(value = "${wechat.callback}")
    private String callBack;


    /*生产二维码链接进行扫码登录*/
    @RequestMapping("/login")
    public String index(Model model) throws Exception {
    
    

        String oauthUrl = "https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect";
        String redirect_uri = URLEncoder.encode(callBack, "utf-8");
        oauthUrl = oauthUrl.replace("APPID", appid).replace("REDIRECT_URI", redirect_uri).replace("SCOPE", scope);
        model.addAttribute("oauthUrl", oauthUrl);

        return "login";
    }


    /*生成自定义二维码*/
    @RequestMapping("/custom")
    public String custom(Model model) throws UnsupportedEncodingException {
    
    

        String redirect_uri = URLEncoder.encode(callBack, "utf-8");

        model.addAttribute("appid", appid);
        model.addAttribute("scope", scope);
        model.addAttribute("redirect_uri", redirect_uri);

        return "custom";
    }


    /*回调方法*/
    @RequestMapping("/callBack")
    public String callBack(String code,Map<String,Object> map) {
    
    

        //1.通过code获取access_token
        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", appid).replace("SECRET", appsecret).replace("CODE", code);
        String tokenInfoStr = HttpRequestUtils.httpGet(url);

        JSONObject tokenInfoObject = new JSONObject(tokenInfoStr);

        //2.通过access_token和openid获取用户信息
        String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
        userInfoUrl = userInfoUrl.replace("ACCESS_TOKEN", tokenInfoObject.getString("access_token")).replace("OPENID", tokenInfoObject.getString("openid"));
        String userInfoStr = HttpRequestUtils.httpGet(userInfoUrl);

        map.put("token", tokenInfoStr);

        /*转为JSON*/
        JSONObject user = new JSONObject(userInfoStr);

        /*只获取openid并返回,openid是微信用户的唯一标识,userInfoStr里面有用户的全部信息*/
        String openid = user.getString("openid");
        map.put("openid", openid);

        /*获取用户头像url*/
        String headimgurl = user.getString("headimgurl");
        map.put("headimgurl", headimgurl);

        /*获取用户昵称*/
        String nickname = user.getString("nickname");
        map.put("nickname", nickname);

        /*获取用户性别*/
        int sex = user.getInt("sex");
        map.put("sex", sex);

        /*获取用户国家*/
        String country = user.getString("country");
        map.put("country", country);

        /*获取用户省份*/
        String province = user.getString("province");
        map.put("province", province);

        /*获取用户城市*/
        String city = user.getString("city");
        map.put("city", city);

        return "callBack";
    }

}

4.Código de página HTML:

1. Haga clic para generar la página del código QR: he insertado una imagen del logotipo de WeChat aquí, haga clic en la etiqueta a para saltar a weChatLogin.htmlInsertar descripción de la imagen aquí

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>wechat登录</title>
</head>
<body>
    <a th:href="${oauthUrl}">
        <img src="../static/wechat_logo.png" alt="微信登录">
    </a>
</body>
</html>

2. Después de llamar al método, regrese a la página de información del usuario callBack.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>授权结果页</title>
</head>
<body>

        <h2>用戶,授权成功!</h2><br>
        <h3>通过code获取access_token 结果:</h3>
        <p th:text="${token}"></p>

        <h3>通过access_token获取用户信息 结果:</h3>
        头像:<img th:src="${headimgurl}" alt="用户头像"><br/>
        openid:<span th:text="${openid}"></span><br/>
        昵称:<span th:text="${nickname}"></span><br/>
        性别:<span th:text="${sex}"></span><br/>
        国家:<span th:text="${country}"></span><br/>
        省份:<span th:text="${province}"></span><br/>
        城市:<span th:text="${city}"></span>

</body>
</html>

3. Insertar (código QR personalizado) custom.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>内嵌(自定义二维码)</title>
</head>
<script src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
<body>

<center><div id="login_container"></div></center>
<script th:inline="javascript">
    var obj = new WxLogin({
    
    
        self_redirect:true,
        id:"login_container",
        appid: [[${
    
    appid}]],
        scope: [[${
    
    scope}]],
        redirect_uri: [[${
    
    redirect_uri}]],
        state: "",
        style: "",
        href: ""
    });
</script>
</body>
</html>

5.Resultados de la prueba:

Utilice el nombre de dominio penetrado por la intranet para acceder a la interfaz, porque ha sido asignado al proyecto local en la red pública.

  1. Acceda a la interfaz de inicio de sesión y haga clic en el ícono del logotipo
    Insertar descripción de la imagen aquí

  2. prueba de código de escaneo

Insertar descripción de la imagen aquí

  1. Después de la autorización, llame al método de devolución de llamada para obtener la información del usuario y mostrarla en la página.
    Nota: openid es la identificación única del usuario de WeChat.

Insertar descripción de la imagen aquí

6. Explicación adicional:

En este punto, es casi suficiente iniciar sesión en SpringBoot a través de WeChat sin separar los extremos frontal y posterior. Me gustaría decirles qué hacer si los extremos frontal y posterior están separados.

1. La dirección de devolución de llamada suele ser la página de inicio del sitio web, por ejemplo: www.abc.com
2. El botón frontal genera un código QR a través de la aplicación y la dirección de devolución de llamada
3. Después de que el usuario escanea el código para obtener autorización, el La interfaz WeChat redirigirá a través de la dirección de devolución de llamada de la página de inicio www.abc.com. Habrá un parámetro llamado código
4. En este momento, una vez que el front-end tiene el código, se pasa al método de la interfaz del back-end y el back-end obtiene información del usuario a través del código. Regresar al frente

Resumido en una oración: 1. Genere un código QR en la página de inicio de www.adc.com, 2. Escanee el código para autorizar el inicio de sesión, 3. Utilice los parámetros del código para obtener información del usuario.

No hay casi nada que no pueda simplificarse si lo pensamos dos veces.

Supongo que te gusta

Origin blog.csdn.net/weixin_45377770/article/details/109901312
Recomendado
Clasificación