微信公众号测试-微信授权登录


一、微信官方文档

https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html

二、准备工作

1)一个域名

● 自己备案申请一个域名
● 使用内网穿透工具

我这里使用的是内网穿透工具闪库
使用方法 >点这里< 这是我以前使用的内网穿透工具,使用方法都差不多的

2)微信公众平台测试号配置

① 配置JS接口安全域名(不要带http)
image
② 配置网页授权回调页面域名(不要带http)
image
image
③ 扫码关注测试号
image

3)获取公众平台测试号的 AppID 和 AppSecret

image

三、授权步骤

1.第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据 code 参数;
2.通过 code 参数加上 AppID 和 AppSecret 等,通过 API 换取 access_token;
3.通过 access_token 进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

image

四、实例

- 项目结构
使用 SpringBoot 构建项目

image

1)Maven依赖

<!--用于对JSON格式的数据进行解析和打包-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.75</version>
</dependency>
<!--支持 HTTP 通讯,实现了所有 HTTP 的方法等-->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.3</version>
</dependency>
<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<!--Thymeleaf-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--web-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

2)配置application.yaml文件

# 端口号
server:
  port: 8080
# 微信公众号配置
weChat:
  appid: xxxxx # 微信测试号ID
  appsecret: xxxxxxx # 微信测试号Secret
  token: xxxx # Token
  backUrl: http://byr1vl4.nat.ipyingshe.com # 你的域名
  backApi: /callBack # 登录回调的API

3)配置拦截器解决跨域问题(如跨域没问题,可忽略)

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class CrossInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        return true;
    }
}

4)公众平台测试号接口配置(可跳过忽略)

测试号配置

URL:填写 http+前面添加的域名+校验API
Token:任意字符串,只要和后端相对应就行

image

DecriptUtil工具类:SHA1加密

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

public class DecriptUtil {

    /**
     * @param decript
     * @return
     */
    public static String SHA1(String decript) {
        try {
            MessageDigest digest = MessageDigest
                    .getInstance("SHA-1");
            digest.update(decript.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }
}

接口校验,接入微信公众平台

Controller

@Controller
public class WxAuthController {

    @Autowired
    private WxAuthService wxAuthService;

    /**
     * 校验接入微信公众平台开发
     *
     * @param signature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @return
     */
    @GetMapping("/wxSignatureCheck")
    @ResponseBody
    public String wxSignatureCheck(
            @RequestParam(value = "signature") String signature,
            @RequestParam(value = "timestamp") String timestamp,
            @RequestParam(value = "nonce") String nonce,
            @RequestParam(value = "echostr") String echostr) {
        return wxAuthService.wxSignatureCheck(signature, timestamp, nonce, echostr);
    }
}

Service

import com.cyan.wx_auth_demo.utils.DecriptUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;

@Slf4j
@Service
public class WxAuthService {

    @Value("${weChat.token}")
    private String token;

    /**
     * 验证签名
     *
     * @param signature
     * @param timestamp
     * @param nonce
     * @param echostr
     * @return 校验成功返回echostr,否则为null
     */
    public String wxSignatureCheck(String signature, String timestamp, String nonce, String echostr) {
        ArrayList<String> array = new ArrayList<>();
        array.add(signature);
        array.add(timestamp);
        array.add(nonce);

        //排序
        String sortString = sort(token, timestamp, nonce);
        //加密
        String mytoken = DecriptUtil.SHA1(sortString);
        //校验签名
        if (mytoken != null && mytoken != "" && mytoken.equals(signature)) {
            log.info("签名校验通过");
            //如果检验成功输出 echostr,微信服务器接收到此输出,才会确认检验完成。
            return echostr;
        } else {
            log.info("签名校验失败");
            return null;
        }
    }

    /**
     * 排序方法
     *
     * @param token
     * @param timestamp
     * @param nonce
     * @return
     */
    public static String sort(String token, String timestamp, String nonce) {
        String[] strArray = {token, timestamp, nonce};
        Arrays.sort(strArray);

        StringBuilder sbuilder = new StringBuilder();
        for (String str : strArray) {
            sbuilder.append(str);
        }

        return sbuilder.toString();
    }
}

5)实现微信授权登录

AuthUtil工具类

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
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.util.EntityUtils;

import java.io.IOException;

@Slf4j
public class AuthUtil {

    public static JSONObject doGetJson(String url) throws ClientProtocolException, IOException {
        JSONObject jsonObject = null;

        //创建HttpClient对象,发送请求,获取数据
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //创建httpGet方法对象
        HttpGet httpGet = new HttpGet(url);
        //设置请求头
        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36");
        //发送请求,获取响应的数据
        log.info("请求地址:{}", url);
        CloseableHttpResponse response = httpClient.execute(httpGet);

        //获取响应体
        HttpEntity entity = response.getEntity();
        if (entity != null) {
            // 把返回的结果转换为JSON对象
            String result = EntityUtils.toString(entity, "GB2312");
            log.info("响应结果:{}", result);
            jsonObject = JSONObject.parseObject(result);
        }
        httpGet.releaseConnection();
        return jsonObject;
    }
}

网站主页,用户点击登录按钮跳转登录授权页面

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class IndexController {

    /**
     * 登录按钮
     * http://byr1vl4.nat.ipyingshe.com/index
     *
     * @return
     */
    @GetMapping("/index")
    public String login() {
        return "<a href='http://byr1vl4.nat.ipyingshe.com/authorize'>微信登录</a>";
    }
}

网页登录授权控制类

import com.alibaba.fastjson.JSONObject;
import com.cyan.wx_auth_demo.utils.AuthUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.io.IOException;
import java.net.URLEncoder;

@Slf4j
@Controller
public class WxAuthController {

    @Value("${weChat.appid}")
    private String appid;

    @Value("${weChat.appsecret}")
    private String appsecret;

    @Value("${weChat.backUrl}")
    private String backUrl;

    @Value("${weChat.backApi}")
    private String backApi;

    /**
     * 一、公众号微信登录授权
     * <p>
     * 通过微信接口获取code
     * 1、如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE
     * 2、获取到 code 与 state
     *
     * @return
     */
    @GetMapping("/authorize")
    public String authorize() throws IOException {

        // 第一步:用户同意授权,获取code
        String redirectUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid
                + "&redirect_uri=" + URLEncoder.encode(backUrl + backApi, "UTF-8")
                + "&response_type=code"
                + "&scope=snsapi_userinfo"
                + "&state=STATE#wechat_redirect";

        // 重定向地址
        System.out.println("重定向至微信登录授权地址: " + redirectUrl);
        return "redirect:" + redirectUrl;
    }

    /**
     * 二、回调获取用户信息
     *
     * @param code 第一步获取到的code
     * @return
     * @throws IOException
     */
    @GetMapping("/callBack")
    @ResponseBody
    public String callBack(String code) throws IOException {

        // 1、通过code(authorize方法获取)换取网页授权access_token
        String accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?"
                + "appid=" + appid
                + "&secret=" + appsecret
                + "&code=" + code
                + "&grant_type=authorization_code";
        JSONObject accessTokenObj = AuthUtil.doGetJson(accessTokenUrl);

        // 2、拉取用户信息,传参 access_token 和 openId
        String userinfoUrl = "https://api.weixin.qq.com/sns/userinfo?"
                + "access_token=" + accessTokenObj.getString("access_token")
                + "&openid=" + accessTokenObj.getString("openId")
                + "lang=zh_CN";
        JSONObject userInfoObj = AuthUtil.doGetJson(userinfoUrl);

        // 将用户信息返回到前端
        StringBuilder sb = new StringBuilder();
        sb.append("<div>");
        sb.append("<h3>授权成功</h3>");
        sb.append("<img alt='头像' src='" + userInfoObj.getString("headimgurl") + "'>");
        sb.append("<p>" + userInfoObj.getString("nickname") + "</p>");
        sb.append("<p>" + userInfoObj.getString("province") + "</p>");
        sb.append("</div>");
        return sb.toString();
    }
}

运行结果

① 登录页
image
② 授权页
image
② 授权成功页
image

到此,微信授权登录成功,如果有运行问题请自行调试,我这边能正常运行的。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM