微信授权登录 (第三方登录)

前言

在写毕业设计时候,有考虑过第三方登录相关实现。当时找的不详细,找到的是微信开放平台。这个开发平台接入微信授权登录需要进行企业认证所以当时就抛弃了该想法。
但最近又接触了一下发现还有个微信公众平台,这个里面申请个人开发的即可测试一下微信授权登录相关的流程。(ps:纯学习记录,生产上线肯定没以下实现这么简单)
微信开发平台和微信公众平台的区别大家可以去网上搜一下这里就不罗列了
开通相关订阅号微信公众号平台账号这些步骤本文就不介绍了。

接入微信公众平台开发

微信接入官方文档

  1. 配置接入的url地址和token,用于测试微信是否能调通你系统的接口。
    其中url是微信进行调用的接口,这个地址必须是外网可以访问的,这里有两种解决方案。
    第一:每次写完的代码都发布到云服务器上面(此处你还需要有云服务器,并且每次发布也麻烦所以推荐第二种)
    第二:使用内网穿透技术,使得你项目地址可以供外网使用。相关博客:https://blog.csdn.net/weixin_43118891/article/details/113104835
    在这里插入图片描述
    在这里插入图片描述
  2. 编写后台代码,进行微信调用的接受地址是:"/wechat/wx" ,这个就是上图中除了域名外的访问地址。
    注意红框中原样返回echostr字段,若不返回或错误返回,在配置页面会提示:配置失败
@RestController
@RequestMapping("/wechat")
public class WechatController {
    private static String WECHAT_TOKEN = "DQICY";

    @RequestMapping("/wx")
    public String get(HttpServletRequest request){
        System.out.println("微信请求进来了");

        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("log: " + log);

        }

        String signature = request.getParameter("signature");/// 微信加密签名
        String timestamp = request.getParameter("timestamp");/// 时间戳
        String nonce = request.getParameter("nonce"); /// 随机数
        String echostr = request.getParameter("echostr"); // 随机字符串

        System.out.println("signature : " + signature + " timestamp: " + timestamp + " nonce: " + nonce + " echostr:" + echostr);
        return echostr;  //回调回去,返回echostr这个字符串,微信会判断你已经成功联调。
    }

    

}

在这里插入图片描述

关注自己的测试公众号

这一步主要是之后扫登录授权二维码时候,不关注公众号会提示需要关注。所以先执行该步骤
在这里插入图片描述

设置回调域名

设置系统对应的公网域名,如下图其实映射关系是
http://gmhta6.natappfree.cc -> 127.0.0.1:9191 (这一步你应该在上面接入微信平台时候已经做了内网穿透或者部署到云服务器上)
在这里插入图片描述
在这里插入图片描述

微信授权业务实现

官方原话下面步骤按着原话梳理,相关开发文档

具体而言,网页授权流程分为四步:

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

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

3、如果需要,开发者可以刷新网页授权access_token,避免过期

4、通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)

1.引导用户进入授权页面,获取code

其实就是让用户打开以下url:https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
其中相关参数例如appid可以看开发文档中有提及,这里不一一介绍,其中的参数我以自己的为例子展示

appid : 你对应的appid
redirect_uri :http://gmhta6.natappfree.cc/wechat/auth  #你系统设置的回调接口("http://域名/wechat/auth")
scope: snsapi_userinfo

然后怎么让用户打开url呢,我这里的解决方案是简化的,就是把url放到网络上的二维码生成器中,生成相应的二维码然后保存图片放到程序中展示给用户扫描。如果要符合逻辑一点你可以在程序中实现一个生成二维码的代码
(注意:这个图片展示地址一定要在你所配置的公网域名下即之前配置的授权回调域名下,微信会检测图片所在位置 即图片地址:http://授权回调域名/static/img.png)
在这里插入图片描述

2.通过code换区网页授权access_token

  1. 如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。
  2. 上面一步已经配置了用户访问网址时候的回调接口。参数:redirect_uri
  3. 在回调接口中获取回调url中的参数,即code和state。
@RequestMapping("/auth")
    public String auth(@RequestParam("code") String code,
                       @RequestParam("state") String state)

在这里插入图片描述

  1. 根据code换取页面授权的access_token,这里使用restTemplate进行远程调用
//使用code和开发者信息拼接调用地址
String codeUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code= " + code + "&grant_type=authorization_code";
RestTemplate restTemplate = new RestTemplate();
//解决乱码,以utf-8编码格式获取,不加这个会乱码
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
//调用地址获取返回值
String responseCode = restTemplate.getForObject(codeUrl,String.class);
//利用gson解析返回值
Map<String,String> map = new Gson().fromJson(responseCode, Map.class);
//获取相关信息
String access_token = map.get("access_token");
String refresh_token = map.get("refresh_token");
String openid = map.get("openid");

在这里插入图片描述

3.刷新access_token(如果需要)

  1. 上述通过code已经换取了access_token 、refresh_token 、openid 。然后access_token默认超时时间是7200s,即2小时。超时后可以使用refresh_token进行刷新。
//利用refresh_token刷新,这里展示如何使用,对于怎么存储获得的参数就不演示了。
String codeUrl = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=" + refresh_token ;
RestTemplate restTemplate = new RestTemplate();
//解决乱码,以utf-8编码格式获取,不加这个会乱码
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
//调用地址获取返回值
String responseCode = restTemplate.getForObject(codeUrl,String.class);
//利用gson解析返回值
Map<String,String> map = new Gson().fromJson(responseCode, Map.class);

在这里插入图片描述

扫描二维码关注公众号,回复: 12437994 查看本文章

4.拉取用户信息(需第一步中scope为 snsapi_userinfo)

//利用access_token和openid拼接地址
String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token +"&openid=" + openid + "&lang=zh_CN";
RestTemplate restTemplate = new RestTemplate();
//解决乱码
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
String responseInfo = restTemplate.getForObject(url,String.class);
Map<String,String> mapInfo = new Gson().fromJson(responseInfo, Map.class);
//获取相关信息
String nickname = mapInfo.get("nickname");
String headimgurl = mapInfo.get("headimgurl");

下面粘贴我整个控制类的方法 就只有一个controller

@RestController
@RequestMapping("/wechat")
public class WechatController {
    private static String WECHAT_TOKEN = "DQICY";

    //用于接入微信公众号平台,接受微信发来的测试报文
    @RequestMapping("/wx")
    public String get(HttpServletRequest request){
        System.out.println("微信请求进来了");

        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("log: " + log);

        }

        String signature = request.getParameter("signature");/// 微信加密签名
        String timestamp = request.getParameter("timestamp");/// 时间戳
        String nonce = request.getParameter("nonce"); /// 随机数
        String echostr = request.getParameter("echostr"); // 随机字符串

        System.out.println("signature : " + signature + " timestamp: " + timestamp + " nonce: " + nonce + " echostr:" + echostr);
        return echostr;  //回调回去,返回echostr这个字符串,微信会判断你已经成功联调。
    }

    //用于接受打开地址后,微信调用的回调页面
    //作用获取code,然后获取用户信息
    //其中一些appid这种我会乱改,修改时候注意开发者相关参数
    @RequestMapping("/auth")
    public String auth(@RequestParam("code") String code,
                       @RequestParam("state") String state){
        //获取微信用户授权后回调函数,获取code
        System.out.println("code : " + code);

        System.out.println("------------------------");

        //根据code获取用户信息  openid等
        String codeUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=wxa111fc19&secret=e5c1a11ec1b1191111&11de=" + code + "&grant_type=authorization_code";
        RestTemplate restTemplate = new RestTemplate();
        //解决乱码
        restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
        String responseCode = restTemplate.getForObject(codeUrl,String.class);
        System.out.println("response={}" + responseCode);
        Map<String,String> map = new Gson().fromJson(responseCode, Map.class);
        String access_token = map.get("access_token");
        String refresh_token = map.get("refresh_token");
        String openid = map.get("openid");
        //获取微信信息

        String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token +"&openid=" + openid + "&lang=zh_CN";
        String responseInfo = restTemplate.getForObject(url,String.class);
        Map<String,String> mapInfo = new Gson().fromJson(responseInfo, Map.class);
        String nickname = mapInfo.get("nickname");
        String headimgurl = mapInfo.get("headimgurl");

        return "nickname : " + nickname + " -- headimgurl : " + headimgurl;
    }

}

猜你喜欢

转载自blog.csdn.net/weixin_43118891/article/details/113125890