微信扫码登录实战(附代码)

作者 | 来碗Java

编辑 | 王久一

公号 | Java葵花宝典

导读: 由于微信端流量比较足,所以扫码登录系统功能也受到了很多系统的青睐,本文就来详细的解开该技术的面纱。 优质内容请关注微信公众号“Web项目聚集地”

演示效果

准备工作

1. 需要一个微信开放平台账号,并创建一个网站应用

点击查看该应用,将appid appSecret获取下来,我们后面会用到。

2. 本地启动ngrok,用来配合调试扫码登录授权回调

启动如下:

3. 将本地内网穿透的地址配置进网站应用里面的开发信息-授权回调域

本例所用到的技术

  • Spring-Boot
  • Thymeleaf
  • Httpclient
  • Json

本例学习要达到的目标

  • 生成全屏网页二维码以及定制化二维码,后者可以进行二维码大小调整,页面布局自行调整,前者则是固定的页面和二维码
  • 分析接入流程和实现功能
  • 列出来的技术

实战

创建spring-boot项目 ,引入相关jar依赖

<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.1</version>
    </dependency>   
    <dependency>
      <groupId>org.json</groupId>
      <artifactId>json</artifactId>
      <version>20160810</version>
</dependency>

配置文件

spring.thymeleaf.prefix: classpath:/templates/
spring.thymeleaf.suffix: .html
#微信开放平台创建的网站应用的appsecret
appsecret=
#微信开放平台创建的网站应用的appid
appid=
scope=snsapi_login
#微信开放平台创建的网站 设置的授权回调域
domain=http://test.xcx.cxylt.cn/

server.port=8083

授权流程说明

微信OAuth2.0授权登录让微信用户使用微信身份安全登录第三方应用或网站,在微信用户授权登录已接入微信OAuth2.0的第三方应用后,第三方可以获取到用户的接口调用凭证(access_token),通过access_token可以进行微信开放平台授权关系接口调用,从而可实现获取微信用户基本开放信息和帮助用户实现基础开放功能等。

微信OAuth2.0授权登录目前支持authorization_code模式,适用于拥有server端的应用授权。该模式整体流程为:

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

简单来讲就是用户在页面生成二维码扫码后进入回调地址,回调地址可以获取code,通过code可以获取accessToken,通过accessToken则可以获取用户的全部信息

第一个二维码页面

后端代码,生成授权地址,让用户点击扫码登录

@RequestMapping("/")
    public String index(Model model) throws UnsupportedEncodingException {
        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("name","liuzp");
        model.addAttribute("oauthUrl",oauthUrl);
        return "index";
}

前端代码

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
        <h1>hello! <label th:text="${name}"></label></h1>
        <a  th:href="${oauthUrl}">点击扫码登录</a>
</body>
</html>

编写授权后回调方法

@RequestMapping("/callBack")
    public String callBack(String code,String state,Model model) throws Exception{
        logger.info("进入授权回调,code:{},state:{}",code,state);

        //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,null,null);

        JSONObject tokenInfoObject = new JSONObject(tokenInfoStr);
        logger.info("tokenInfoObject:{}",tokenInfoObject);

        //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,null,null);
        logger.info("userInfoObject:{}",userInfoStr);

        model.addAttribute("tokenInfoObject",tokenInfoObject);
        model.addAttribute("userInfoObject",userInfoStr);

        return "result";
    }

回调后跳转页面,这个页面记录授权获取的信息

<!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>
     <h2>你好,授权成功!</h2><br>
     <h3>通过code换取access_token 结果:</h3>
     <p th:text="${tokenInfoObject}"></p>
     <h3>通过access_token获取用户信息 结果:</h3>
     <p th:text="${userInfoObject}"></p>
</body>
</html>

自定义二维码页面

后端路由

@RequestMapping("/1")
    public String index1(Model model) throws UnsupportedEncodingException {
        String redirect_uri = URLEncoder.encode(callBack, "utf-8"); ;
        model.addAttribute("name","liuzp");
        model.addAttribute("appid",appid);
        model.addAttribute("scope",scope);
        model.addAttribute("redirect_uri",redirect_uri);
        return "index1";
}

前台页面

<!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>
        <h1>hello! <label th:text="${name}"></label></h1>
        <div id="login_container"></div>
    <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>

两个页面结果页和回调地址都是一致的,这里只是提供两种做法。

原文发布于微信公众号 - Web项目聚集地(web_resource)

原文发表时间:2018-09-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java架构

Facebook顶级架构师教你怎么使用Java来搭建微服务快速预览介绍$java -jar myservice.jarSelf-containedSpring BootWildfly SwarmIn-

2709
来自专栏Linyb极客之路

Spring Boot十种安全措施

941
来自专栏一个会写诗的程序员的博客

Gatling : 次时代性能测试利器

Gatling作为一款开源免费的性能测试工具越来越受到广大程序员的欢迎。免费当然是好的,最缺钱的就是程序员了;开源更好啊,缺啥功能、想做定制化的可以自己动手,丰...

1192
来自专栏微服务那些事儿

Spring Cloud 系列-执行器端点(Endpoint)

强推一波:https://segmentfault.com/ls/1650000011386794

2374
来自专栏Rainbond开源「容器云平台」

使用Java构建微服务

1122
来自专栏针针小站

【Share】Dell Precision 5510 Mojave Clover分享

首先先感谢 @darkhandz @黑果小兵 @Scottsanett 等大佬的分享

9032
来自专栏向治洪

hibernate 5.2.6新特性

概述 Hibernate ORM 5.2.6 发布了,Hibernate是一种Java语言下的对象关系映射解决方案。 它是使用GNU宽通用公共许可证发行的自由、...

2119
来自专栏FreeBuf

现代版荆轲刺秦王:Struts2 REST插件漏洞分析

战国末期,大秦实力强盛,大有横扫六合之势,在灭了韩、赵两国后,下一个目标就是燕国。

1052
来自专栏chafezhou

WSL和pipenv用起来

2105
来自专栏极客猴

Django 学习笔记之环境搭建

古人云:功遇善其事,必先利其器。在正式学习 Django Web 框架之前,我们要把准备工作做好。准备工作主要是搭建开发环境,具体工作是安装 Python、创建...

822

扫码关注云+社区

领取腾讯云代金券