文章目录

  • 1. 准备
  • 2. 测试
  • 3. 网页授权

本文借鉴于:

https://blog.csdn.net/weixin_45925109/article/details/108515129?spm=1001.2014.3001.5501
https://blog.csdn.net/victoyr/article/details/89648017

两篇博客,如需观看请移步。

1. 准备

微信开发平台网址:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html

由于我这里是没有微信公众号的,只能使用官方提供给我们的测试账号,地址如下:
http://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index

这里最好是准备一台已经备案过得服务器,我这里也是尝试了很多中办法,最后无奈找朋友借了一台备案的服务器,才测试通过。

2. 测试

创建一个 spring boot 项目,勾选 web 依赖即可。创建一个 HelloController 接口代码如下:

package org.javaboy.wechat_login.controller;import org.javaboy.wechat_login.utils.SignUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Enumeration;/*** 描述:** @Author: YLq* @DateTime: 2021/7/15 17:08* @Version 1.0**/
@RestController
public class HelloController {@GetMapping("hello")public String hello(){return "hello";}/*** 微信测试接口*/@RequestMapping(value = "/captchaImage")public void get(HttpServletRequest request, HttpServletResponse response) throws Exception {System.out.println("========WechatController========= ");Enumeration pNames = request.getParameterNames();while (pNames.hasMoreElements()) {String name = (String) pNames.nextElement();String value = request.getParameter(name);// out.print(name + "=" + value);String log = "name =" + name + "     value =" + value;}System.out.println("========WechatControllertets========= ");String signature = request.getParameter("signature");/// 微信加密签名String timestamp = request.getParameter("timestamp");/// 时间戳String nonce = request.getParameter("nonce"); /// 随机数String echostr = request.getParameter("echostr"); // 随机字符串PrintWriter out = response.getWriter();System.out.println("signature:微信加密签名\t"+signature+"\n"+"timestamp:时间戳\t"+timestamp+"\n"+"nonce:随机数\t"+nonce+"\n"+"echostr:随机字符串\t"+echostr);if (SignUtil.checkSignature(signature, timestamp, nonce)) {System.out.println("校验成功!!!!!!!!!!!!!");out.print(echostr);}out.close();out = null;}
}

创建 SignUtil 校验的工具类:

package org.javaboy.wechat_login.utils;import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;/*** 描述:** @Author: YLq* @DateTime: 2021/7/16 15:34* @Version 1.0**/
public class SignUtil {// 与接口配置信息中的Token要一致private static String token = "mytoken";/*** 验证签名* @param signature* @param timestamp* @param nonce* @return*/public static boolean checkSignature(String signature, String timestamp, String nonce) {String[] arr = new String[] { token, timestamp, nonce };// 将token、timestamp、nonce三个参数进行字典序排序Arrays.sort(arr);StringBuilder content = new StringBuilder();for (int i = 0; i < arr.length; i++) {content.append(arr[i]);}MessageDigest md = null;String tmpStr = null;try {md = MessageDigest.getInstance("SHA-1");// 将三个参数字符串拼接成一个字符串进行sha1加密byte[] digest = md.digest(content.toString().getBytes());tmpStr = byteToStr(digest);} catch (NoSuchAlgorithmException e) {e.printStackTrace();}content = null;// 将sha1加密后的字符串可与signature对比,标识该请求来源于微信return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;}/*** 将字节数组转换为十六进制字符串* @param byteArray* @return*/private static String byteToStr(byte[] byteArray) {String strDigest = "";for (int i = 0; i < byteArray.length; i++) {strDigest += byteToHexStr(byteArray[i]);}return strDigest;}/*** 将字节转换为十六进制字符串* @param mByte* @return*/private static String byteToHexStr(byte mByte) {char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };char[] tempArr = new char[2];tempArr[0] = Digit[(mByte >>> 4) & 0X0F];tempArr[1] = Digit[mByte & 0X0F];String s = new String(tempArr);return s;}
}

接着,在微信提供给我们的 测试号管理 中,进行测试。

url,解释我们后台程序的 url 地址,是带有域名的地址
token,后台配置的 token

测试结果如下:

证明可以访问到我们的程序了。

注意: url 地址,必须是一个备案的服务器的域名,上面的博客中提到了使用小米球(我也尝试使用了花生壳)。虽然,在这个环节上是可以发送给到自己的程序上的,但是在接下来,微信用户同意授权的步骤中,在微信上发送 url 地址会被微信屏蔽掉,所以不建议使用。

3. 网页授权

JS接口安全域名,这里直接放置自己服务器的域名。

测试号二维码
扫码关注该公众号,然后进行测试。

接着修改网页授权获取用户基本信息:

这里修改,填的是域名

接着就是代码部分,我这里按照上面博客的代码进行了少量的删减,如有不清楚的请移步上面的博客。

创建 WechatLoginController

package org.javaboy.wechat_login.controller;import com.fasterxml.jackson.databind.ObjectMapper;
import org.javaboy.wechat_login.utils.WechatUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;/*** 描述:** @Author: YLq* @DateTime: 2021/7/16 16:06* @Version 1.0**/
@Controller
@RequestMapping("wechatlogin")
public class WechatLoginController {private static Logger log = LoggerFactory.getLogger(WechatLoginController.class);@RequestMapping(value = "/logincheck", method = { RequestMethod.GET })public String doGet(HttpServletRequest request, HttpServletResponse response) {log.debug("weixin login get...");// 获取微信公众号传输过来的code,通过code可获取access_token,进而获取用户信息String code = request.getParameter("code");// 这个state可以用来传我们自定义的信息,方便程序调用,这里也可以不用// String roleType = request.getParameter("state");log.debug("weixin login code:" + code);String user = null;String openId = null;if (null != code) {String token;try {// 通过code获取access_tokentoken = WechatUtil.getUserAccessToken(code);System.out.println("token = " + token);ObjectMapper objectMapper = new ObjectMapper();HashMap<String,String> hashMap = objectMapper.readValue(token, HashMap.class);System.out.println("hashMap = " + hashMap);String refreshToken = hashMap.get("refresh_token");System.out.println("refreshToken = " + refreshToken);String openid = hashMap.get("openid");System.out.println("openid = " + openid);String url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx0a03cef7d9802ef9&secret=0e01d9ac45803832f756c71c121b667b";String s = WechatUtil.httpsRequest(url, "GET", null);String accessToken = hashMap.get("access_token");System.out.println("accessToken = " + accessToken);HashMap<String,String> map = objectMapper.readValue(s, HashMap.class);System.out.println("s = " + s);// 通过access_token和openId获取用户昵称等信息user = WechatUtil.getUserInfo(accessToken, openId);System.out.println("user = " + user);request.getSession().setAttribute("openId", openId);} catch (IOException e) {log.error("error in getUserAccessToken or getUserInfo or findByOpenId: " + e.toString());e.printStackTrace();}}// ======todo begin======// 前面咱们获取到openId后,可以通过它去数据库判断该微信帐号是否在我们网站里有对应的帐号了,// 没有的话这里可以自动创建上,直接实现微信与咱们网站的无缝对接。// ======todo end======if (user != null) {// 获取到微信验证的信息后返回到指定的路由(需要自己设定)return "frontend/index";} else {return null;}}/**
* 生成 url 发送到微信内部
*/public static void main(String[] args) throws UnsupportedEncodingException {String encode = URLEncoder.encode("http://itzgm.cn/wechatlogin/logincheck","UTF-8");StringBuffer buffer = new StringBuffer();buffer.append(" https://open.weixin.qq.com/connect/oauth2/authorize?").append("appid=").append("wx0a03cef7d9802ef9").append("&redirect_uri=").append(encode).append("&response_type=code&scope=snsapi_base&state=45897852#wechat_redirect");String s = buffer.toString();System.out.println("s = " + s);}}

发送微信 API 的工具类

package org.javaboy.wechat_login.utils;import org.javaboy.wechat_login.manager.MyX509TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.ConnectException;
import java.net.URL;/*** 描述:** @Author: YLq* @DateTime: 2021/7/16 16:09* @Version 1.0**/
public class WechatUtil {private static Logger log = LoggerFactory.getLogger(WechatUtil.class);/*** 获取UserAccessToken实体类* @param code* @return* @throws IOException*/public static String getUserAccessToken(String code) throws IOException {// 测试号信息里的appIdString appId = "wx0a03cef7d9802ef9";log.debug("appId:" + appId);// 测试号信息里的appsecretString appsecret = "0e01d9ac45803832f756c71c121b667b";log.debug("secret:" + appsecret);// 根据传入的code,拼接出访问微信定义好的接口的URLString url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + appsecret+ "&code=" + code + "&grant_type=authorization_code";// 向相应URL发送请求获取token json字符串String tokenStr = httpsRequest(url, "GET", null);return tokenStr;}/*** 获取WechatUser实体类* @param accessToken* @param openId* @return*/public static String getUserInfo(String accessToken, String openId) {// 根据传入的accessToken以及openId拼接出访问微信定义的端口并获取用户信息的URLString url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openId+ "&lang=zh_CN";// 访问该URL获取用户信息json 字符串String userStr = httpsRequest(url, "GET", null);log.debug("user info :" + userStr);return userStr;}/*** 发起https请求并获取结果* @param requestUrl*            请求地址* @param requestMethod*            请求方式(GET、POST)* @param outputStr*            提交的数据* @return json字符串*/public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {StringBuffer buffer = new StringBuffer();try {// 创建SSLContext对象,并使用我们指定的信任管理器初始化TrustManager[] tm = { new MyX509TrustManager() };SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");sslContext.init(null, tm, new java.security.SecureRandom());// 从上述SSLContext对象中得到SSLSocketFactory对象SSLSocketFactory ssf = sslContext.getSocketFactory();URL url = new URL(requestUrl);HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();httpUrlConn.setSSLSocketFactory(ssf);httpUrlConn.setDoOutput(true);httpUrlConn.setDoInput(true);httpUrlConn.setUseCaches(false);// 设置请求方式(GET/POST)httpUrlConn.setRequestMethod(requestMethod);if ("GET".equalsIgnoreCase(requestMethod))httpUrlConn.connect();// 当有数据需要提交时if (null != outputStr) {OutputStream outputStream = httpUrlConn.getOutputStream();// 注意编码格式,防止中文乱码outputStream.write(outputStr.getBytes("UTF-8"));outputStream.close();}// 将返回的输入流转换成字符串InputStream inputStream = httpUrlConn.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String str = null;while ((str = bufferedReader.readLine()) != null) {buffer.append(str);}bufferedReader.close();inputStreamReader.close();// 释放资源inputStream.close();inputStream = null;httpUrlConn.disconnect();log.debug("https buffer:" + buffer.toString());} catch (ConnectException ce) {log.error("Weixin server connection timed out.");} catch (Exception e) {log.error("https request error:{}", e);}return buffer.toString();}
}

MyX509TrustManager 主要继承 X509TrustManagerhttps 证书信任管理器

package org.javaboy.wechat_login.manager;import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;/*** 描述:** @Author: YLq* @DateTime: 2021/7/16 16:12* @Version 1.0**/
public class MyX509TrustManager implements X509TrustManager {@Overridepublic void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}@Overridepublic void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}@Overridepublic X509Certificate[] getAcceptedIssuers() {return null;}
}

测试结果:

这里我们便能获取到关注公众号人的信息了。但是我这里测试了一下在 第一步:用户同意授权scope的值是 snsapi_userinfo 的时候,到了 第四步:拉取用户信息 才能拉取到,而scope的值是 snsapi_base 的时候则获取不到详细信息。

最后,在自己测试的时候,不要忘记修改成为你自己的 appIDappsecret,还有最重要的就是域名。如上信息,仅供参考!!!

微信公众号——网页授权相关推荐

  1. 微信公众号网页授权--前端获取code及用户信息(vue)

    前段时间开发微信公众号网页授权,虽然网上已经有很多关于这方面的博客或者教程,但是第一次开发还是遇到挺多坑的,以下分享一下我的踩坑填坑之路. 一.测试号相关配置 首先在你公司申请的测试号上配置好相关信息 ...

  2. 微信公众号网页授权--前端获取code及用户信息(vue)【简单详细版】

    嗨喽大家好,前段时间开发微信公众号网页授权,虽然网上已经有很多关于这方面的博客或者教程,但是第一次开发还是遇到挺多坑的,以下分享一下我的遇到的一些问题的见解,希望对你们有帮助. 一.测试号相关配置 首 ...

  3. 微信公众号网页授权思路解析及具体代码

    微信公众号网页授权思路解析及具体代码 微信开发文档 实现方式也是两种: 1.静默授权登录 授权登录以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静 ...

  4. 微信公众号网页授权,获取用户信息以及openid -- PHP后台

    微信公众号网页授权,获取用户信息以及openid 这几天做项目,想通过公众号的appid获取用户的openid就,然后在网上查资料,问朋友,最后找到了方法,就是这个网页授权. 起初一直很蒙,这个怎么弄 ...

  5. 微信公众号网页授权时序图

    微信公众号网页授权时序图 公众号网页授权时序图

  6. 微信公众号网页授权登录的超简单实现步骤

    微信开放平台为第三方移动程序提供分享.传播的接口, 使用户可将第三方程序的内容发布给好友或分享至朋友圈, 下面这篇文章主要给大家介绍了关于微信公众号网页授权登录的超简单实现方法, 需要的朋友可以参考下 ...

  7. 微信公众号网页授权40163问题【php】

    微信公众号网页授权40163问题 tp5为例,emmmm-一直报40163或40029问题,翻遍了各大网站都没找到合适我的办法. 如图: 解决之后如图: 因为重定向所以请求了两次code,所以一直报4 ...

  8. 微信公众号网页授权代码优化过程(一)

    2019独角兽企业重金招聘Python工程师标准>>> 第一次更新 写本系列博客的主要原因是,我在处理一个微信公众号项目时要做一个网页授权的操作(官方地址是https://mp.we ...

  9. php微信授权没有code返回,解决关于微信公众号网页授权获取code参数的问题

    解决关于微信公众号网页授权获取code参数的问题 发布时间:2018-07-24 23:21, 浏览次数:3327 , 标签: code * 在微信网页授权过程中,需要获取code参数,因为我用的是公 ...

  10. 在做微信公众号网页授权的时候,有时会重定向两次网页(302问题)

    在做微信公众平台网页授权时,发现每次请求授权链接 https://open.weixin.qq.com/connect/oauth2/authorize?appid=xxx&redirect_ ...

最新文章

  1. [转]web标准的几个误区
  2. python3.5怎么安装pip-为python 3.5安装pip
  3. GNU make manual 翻译(六十一)
  4. mysql csdn 知乎_CSDN 怎么样?
  5. Linux网络设置(第二版) --互联网寻址过程
  6. mysql数据库和表的关系_MySQL数据库学习【第六篇】表与表之间的关系
  7. CCF202006-4 1246【矩阵快速幂】(100分题解链接)
  8. 未能加载文件或程序集Tianyige.SqlServerDAL问题解决
  9. Luogu2606[ZJOI2010] 排列计数
  10. python实现文件管理系统_Python - 文件管理系统
  11. 海伦公式c语言double,海伦公式
  12. mysql dump 1449_mysqldump 1449错误解决办法
  13. Spring中如何操作JDBC
  14. 印度:农村是IT发展的根据地
  15. Probability and Hypothesis Testing
  16. 基于vue+ionic+capacitor的图书借阅app
  17. “AI+制造第一股”创新奇智敲钟在即,3年多累亏11亿、低毛利待解
  18. CAD软件与常用EDA软件的区别
  19. 性能测试-地铁模型分析
  20. 新房装修是半包好还是全包好一点?

热门文章

  1. vue瀑布流布局插件vue-masonry
  2. 虚幻4引擎开发使用感受
  3. 春款童装产品做短视频营销应该怎么做?短视频营销策略分析
  4. 201809-2买菜
  5. python中import re_python中re模块
  6. Python 鸡兔同笼
  7. 安搭Share:熬夜,对于身体健康的损坏程度,不亚于过度劳累
  8. tx:advice标签
  9. 华为服务器在哪里看型号,服务器型号怎么看
  10. (转)【最新】抖音相关工具合集--在线观看,网页版,去水印下载视频,下载音乐,音乐榜单等