实现微信网页授权登录

 

一、需要有一个公众号(可以使用测试号);

       申请测试号:

            申请测试号网址:点击

            或者进入公众号平台,路径:开发>开发者工具

二、配置测试号信息

   1、接口配置验证

package com.example.wx.controller;

import javax.servlet.http.HttpServletRequest;

import com.example.wx.utils.SignUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.PrintWriter;
import java.util.Enumeration;
import javax.servlet.http.HttpServletResponse;

/**
 * @Description: 微信校验服务器资源
 * @author:chaoyapeng
 * @time:2020/9/16
 * @Version V1.0
 */
@RestController
@Slf4j
public class AgentWeixinReplyController {

    @RequestMapping(value = "/wx/reply")
    public void get(HttpServletRequest request, HttpServletResponse response) throws Exception {
        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;
        }
        String signature = request.getParameter("signature");/// 微信加密签名
        String timestamp = request.getParameter("timestamp");/// 时间戳
        String nonce = request.getParameter("nonce"); /// 随机数
        String echostr = request.getParameter("echostr"); // 随机字符串
        PrintWriter out = response.getWriter();

        if (SignUtil.checkSignature(signature, timestamp, nonce)) {
            log.info("微信校验成功!");
            out.print(echostr);
        }

        out.close();
        out = null;
    }
}
package com.example.wx.utils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

/**
 * @Description: 请求校验工具类
 * @author:chaoyapeng
 * @time:2020/9/16
 * @Version V1.0
 */
public class SignUtil {

    // 与接口配置信息中的Token要一致
    private static String token = "token_core";

    /**
     * 验证签名
     *
     * @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;
    }

}

三、进入公众号开发者中心页配置授权回调域名

      具体位置:接口权限-网页服务-网页账号-网页授权获取用户基本信息-修改

 

四:授权步骤:

    1、引导用户进入授权页面同意授权,获取code

    2、通过code换取网页授权access_token(与基础支持中的access_token不同)

    3、通过网页授权access_token和openid获取用户基本信息

 

  具体请参考: 微信网页授权开发文档

代码实现

AuthUtil工具类:

 

package com.example.wx.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import java.io.IOException;

/**
 * @Description: 微信授权工具类
 * @author:chaoyapeng
 * @time:2020/9/17
 * @Version V1.0
 */
public class AuthUtil {

    public static final String APPID = "wx15df95c5963eadde";
    public static final String APPSECRET = "16a6df30044bf275583c460724bced6b";
    //回调地址
    public static final String backUrl="http://h5.free.qydev.com/callBack";

    public static JSONObject doGetJson(String url) throws IOException {
        JSONObject jsonObject = null;
        //首先初始化HttpClient对象
        DefaultHttpClient client = new DefaultHttpClient();
        //通过get方式进行提交
        HttpGet httpGet = new HttpGet(url);
        //通过HTTPclient的execute方法进行发送请求
        HttpResponse response = client.execute(httpGet);
        //从response里面拿自己想要的结果
        HttpEntity entity = response.getEntity();
        if(entity != null){
            String result = EntityUtils.toString(entity,"UTF-8");
            jsonObject = jsonObject.parseObject(result);
        }
        //把链接释放掉
        httpGet.releaseConnection();
        return jsonObject;
    }

}

controller:

package com.example.wx.controller;

import com.alibaba.fastjson.JSONObject;
import com.example.wx.domain.User;
import com.example.wx.utils.AuthUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;

/**
 * @Description: 微信授权
 * @author:chaoyapeng
 * @time:2020/9/17
 * @Version V1.0
 */
@Controller
@Slf4j
public class WxController {

    /**
     * 引导用户进入授权页面同意授权,获取code
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping(value="wxlogin")
    public void wx(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //第一步:引导用户进入授权页面同意授权,获取code
        StringBuilder builder = new StringBuilder("https://open.weixin.qq.com/connect/oauth2/authorize?appid=");
        builder.append(AuthUtil.APPID);
        builder.append("&redirect_uri=");
        builder.append(URLEncoder.encode(AuthUtil.backUrl));//开发文档要求转换
        builder.append("&response_type=code");
        builder.append("&scope=snsapi_userinfo");
        builder.append("&state=STATE#wechat_redirect");
        //授权页面地址
        //将StringBuilder转换成String
        String url = builder.toString();
        //重定向到授权页面
        response.sendRedirect(url);
    }

    /**
     * 通过第一步获取的code换取网页授权access_token和openid
     * @param code
     * @param model
     * @return
     * @throws IOException
     */
    @RequestMapping(value="callBack")
    public String wxcallback(@RequestParam("code") String code, Model model)throws IOException {
        log.info("code:{}",code);
        //获取code后,请求以下链接获取access_token
        StringBuilder builder = new StringBuilder("https://api.weixin.qq.com/sns/oauth2/access_token?appid=");
        builder.append(AuthUtil.APPID);
        builder.append("&secret=");
        builder.append(AuthUtil.APPSECRET);
        builder.append("&code=");
        builder.append(code);
        builder.append("&grant_type=authorization_code");

        //通过网络请求方法来请求上面这个接口
        //将StringBuilder转换成String
        String url = builder.toString();
        JSONObject jsonObject = AuthUtil.doGetJson(url);
        log.info("jsonObject:{}",jsonObject);
        //从返回的JSON数据中取出access_token和openid,拉取用户信息时用
        String token = jsonObject.getString("access_token");
        String openid = jsonObject.getString("openid");

        // 第三步:刷新access_token(如果需要)

        // 第四步:拉取用户信息(需scope为 snsapi_userinfo)
        StringBuilder builder1 = new StringBuilder("https://api.weixin.qq.com/sns/userinfo?access_token=");
        builder1.append(token);
        builder1.append("&openid=");
        builder1.append(openid);
        builder1.append("&lang=zh_CN");
        //通过网络请求方法来请求上面这个接口
        //将StringBuilder转换成String
        String infoUrl = builder1.toString();
        JSONObject userInfo = AuthUtil.doGetJson(infoUrl);

        log.info("userInfo:{}",userInfo);

        model.addAttribute("info",userInfo);
        return "wx/index";
    }

}

前端显示页面是使用thymeleaf模板

<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>授权成功</title>
</head>
<body>
    <div><img width="100" th:src="${info.headimgurl }"></div>
    <div>昵称:<font th:text="${info.nickname}"></font></div>
    <div>地址:<font th:text="${info.country}"></font></div>
    <div>openId:<font th:text="${info.openid}"></font></div>
</body>
</html>

五、自定义菜单

 

      使用微信公众平台接口调试工具

     1、填写appid、appsecret获取access_token

 

      2、自定义菜单

 

body内容:

{
     "button": [
          {
               "name": "授权",
               "sub_button": [
                    {
                         "type": "view",
                         "name": "获取授权",
                         "url": "http://h5.free.qydev.com/wxlogin"
                    }
               ]
          }
     ]
}

      菜单效果图:

六、效果

 

 

 

 

 

 

 

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值