如何实现小程序登录鉴权

为了方便用户使用小程序时,使用微信账号授权快速登录软件,微信小程序提供了相关的授权接口。小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。以便但是对于新手来说,配置起来还是有些难度。

本文将对小程序使用微信授权做较为详细的介绍,并提供简单的服务端及客户端demo代码以方便大家学习。在开始之前,我们首先要了解几个知识点,我们的目的是什么?我们需要哪些参数?用参数来做什么?

目标

我们的目标很简单,能够让用户点击登录按钮后,通过某种方式获取用户的相关信息,而这里的信息是唯一的,后续不管用户更换多少设备,都能确定用户的唯一性。而且这里的数据要足够安全,不能任何人都能通过某种技术去获取。这里的数据能够存储,将这个数据存储在业务相关的服务器,下次能够直接读取确认用户。

带着这几个目标,我们发现微信其实提供了相关的登录能力,系统了相关的API以方便我们使用,比如小程序端的wx.login,服务器端的code2Session,微信接口端的openid等数据,那么这这些参数,这些数据有什么用呢?请向下看。

流程

在开始之前,我们先看看小程序官方给出的小程序登录流程时序图,一下子没看懂?没关系,接下来就给大家做详细的介绍。

img

上面这张图与我们常见的流程图还是有些出入,我通过自己的理解,画出了下面的这张图,我们一起来看看。

这张图是是简单了不少,我们看到,小程序首先通过wx.login()函数获取当前用户的code,然后再通过wx.request将code传送到服务器。服务器端将appidappsecretcode等参数通过request提交到微信服务接口,微信服务接口反馈openidsession_key参数。我们发现,小程序通信不只是和服务器端进行了通信,还与微信服务接口进行了通信,那么,这里的服务器端和微信服务端起着什么样的作用了,在本流程中起着什么样子的角色呢?

小程序

小程序端,我们需要两个函数一个变量,两个函数为wx.login()函数和wx.request()函数,变量为code变量。这两个函数及变量都是小程序官方提供的,我们只需要直接使用即可。

  • wx.login() - wx.login()在本教程中的目的是调用接口获取登录凭证(code)。
  • code - 用户登录凭证(有效期五分钟),登录凭证 code 只能使用一次。
  • wx.request() - wx.request()将用户登录凭证code传输到开发者服务器后台调用。

在小程序的流程中,其实主要就做了两件事,第一件事是通过wx.login()函数生成code,第二件事就是通过wx.request()函数将code提交到你自己搭建的小程序的服务器。

wx.login()这个API的作用就是为当前用户生成一个临时的登录凭证,这个临时登录凭证的有效期只有五分钟。有了这个凭证,我们才能通过服务器获取当前用户的appid

wx.request()这个API的作用发起 HTTPS 网络请求。发起HTTPS请求的方式很多,比如GET、POST等方式,因篇幅限制,本文就不过多介绍,感兴趣的同学可以参考小程序wx.request官方文档。本文仅使用GET方式进行传参。

服务器

在服务器端,我们需要获取小程序的 appId,小程序的 appSecret,以及通过小程序wx.request()传输过来的code,还包括默认的授权类型,我们填写authorization_code即可。最后,我们要通过官方的authorization_code方法,获取openidsession_keyunionid等参数。

  • appId - 小程序的ID,这个ID是唯一的,可以进入小程序设置-开发设置中获取。
  • appSecret - 小程序密钥,也是唯一的,可以进入小程序设置-开发设置中获取,如果忘记,可以点击重置。
1541140868225

微信服务接口

最后,我们在服务器端将上面获取到的appidappSecretcode参数HTTP请求微信服务器,等待微信返回openidsession_keyunionid这三个参数。之后,在通过服务器鉴权,给小程序返回相应数据。

  • openid - 用户唯一标识,每个用户请求得到的标识不同,但是同一用户每次请求得到的这个数据是相同的。
  • session_key - 会话密钥,每次请求返回的会话密钥不同,主要用于请求其他数据时解密。会话密钥 session_key 是对用户数据进行 加密签名 的密钥。为了应用自身的数据安全,开发者服务器不应该把会话密钥下发到小程序,也不应该对外提供这个密钥

整体的流程就是这个样子,可能有人问,为什么我不直接在小程序端向微信服务器发起HTTP请求呢?这样不需要微信接口服务,直接从小程序端就能获取openid等数据了,何必多此一举呢?目的很简单,为了数据安全,将需要保密的数据都存放在服务器端,防止数据暴漏,这也是微信官方的建议,将重要数据存储在服务器端,微信会对这些数据做签名和加密处理。开发者后台拿到开放数据后可以对数据进行校验签名和解密,来保证数据不被篡改。

小程序端

明白了整体的流程和架构,我们就可以开始撰写代码了,首先,我们需要安装开发环境,及搭建好基础的代码框架,没有经验的同学可以参考如何入门小程序开发这篇文章,在此文中,我们详细介绍了入门小程序应该具备的工具及代码。我们需要在index.jsindex.wxml中插入下面的代码。

编辑index.wxml,插入下面的代码,这里我们插入一个button来调用wx_login()函数,每次点击请求登录按钮,将会自动调用index.js内的wx_login()函数。之后,wx_login()返回openid显示。(理论上来说openid不应该在客户端展示,为了演示,将openid发送至客户端,如果在生产环境使用,请尽量将openid保留在服务器

<button type="primary" bindtap="wx_login">请求登录</button>
<text class='text-red'>当前openid:{{openid}}</text>

接下来,打开index.js,在page({})中插入下面的代码,

  wx_login() {
    var myThis = this;
    wx.login({
      success(res) {
        if (res.code) {
          wx.request({
            url: 'https://你服务器的请求地址',
            data: {
              code: res.code
            },
            success(res) {
              myThis.setData({
                openid: res.data.openid
              })
            }
          })
        } else {
          console.log('登录失败!' + res.errMsg)
        }
      }
    })
  },

之后,你的页面可能如下所示,注意,代码中的url一定要更换为你服务器的地址,并确保其通过https加密,并在小程序开发者平台绑定,关于如何加密绑定,可以参考如何快速搭建微信小程序这篇文章。代码中,我们通过wx.login()中的res.code去获取当前的用户登录凭证code,然后通过wx.request()code提交到你的服务器。并等待返回结果res.data.openid

1541144650075

小程序端代码逻辑代码很简单,接下来,我们要撰写在服务端的代码。

服务器端

服务端的环境有很多选择NodeJS、PHP、Python等大部分主流语言都可以部署HTTP服务,今天我们将教大家使用PHP语言进行环境部署,其他语言请同学们自行部署。

安装环境

我这里以Ubuntu Server 16.04 LTS为例,我们需要安装php运行环境及NginxWeb服务,同时也需要申请免费的SSL证书和域名,关于证书和域名的申请注册请参考如何快速搭建微信小程序这篇文章。注册完域名及证书,我们就可以开始部署服务器了!首先,登录服务器,执行下面的命令。

sudo apt update
sudo apt install php php-fpm php-curl nginx -y

安装完成后,使用浏览器访问你的服务器IP地址,如果看到下面的内容,则证明Web服务已经启动。

1541146155445

因为小程序获取远程数据,必须为HTTPS环境,所以目前搭建的环境,在小程序无法使用,接下来,我们将使用SSL证书加密小程序访问你服务器之间的流量。这里就需要刚才注册的域名及证书了。首先,将下载的证书,上传到你的服务器,并记录下这个位置。然后,我们将配置Nginx服务,以让其支持HTTPS流量。

我们找到/etc/nginx/conf.d文件夹,新建配置文件,为了方便后续修改,我将这里的配置文件修改为weixin.techeek.cn.conf大家可以根据自己的需求修改。

cd /etc/nginx/conf.d
sudo nano weixin.techeek.cn.conf

nano编辑器中,我们写下下面的代码

server {
        listen 443 ssl;
        server_name weixin.techeek.cn;
				index  index.php index.html index.htm;
				root /usr/share/nginx/html;
        ssl_certificate      /home/ubuntu/1_weixin.techeek.cn_bundle.crt;
        ssl_certificate_key  /home/ubuntu/2_weixin.techeek.cn.key;
        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location ~ .php$ {
        fastcgi_pass  unix:/run/php/php7.0-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

server {
        listen 80 default_server;
        server_name weixin.techeek.cn;
        root /usr/share/nginx/html;
        index index.php index.html index.htm;
        location / {
                try_files $uri $uri/ =404;
        }
}

一定注意,将文中server_name中的weixin.techeek.cn更换成你的域名。将ssl_certificatessl_certificate_key中证书的路径更换成你刚上传证书的路径。然后,执行下面的命令重启nginx服务。

sudo service nginx restart

之后,打开你电脑的浏览器,然后通过域名访问,注意,这里一定要在域名前加https://,比如我访问的域名https://weixin.techeek.cn

1541147802445

如果域名前有小锁标志,则证明你已经配置成功,可以开始下一步了。

运行环境

服务端已经配置完成,接下来我们就需要撰写服务端代码了,代码也很简单,我们需要将其放在/usr/share/nginx/html这个目录下,使用下面的命令。

cd /usr/share/nginx/html
sudo nano index.php

之后,使用nano编辑器撰写下面的代码。

<?php
$code = $_GET["code"];
$curl = curl_init();
curl_setopt_array($curl, array(
  CURLOPT_URL => "https://api.weixin.qq.com/sns/jscode2session?appid=wx**********b&secret=0a6****************540&js_code=". $code ."&grant_type=authorization_code",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "GET",
));

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

注意,将代码中的wx**********b0a6****************540替换为你在小程序管理页面获取到的appidAppSecret,之后保存。(这段代码中,为了方便演示,我直接将openidsession_key等参数返回给了小程序,如果你是在生产环境使用,务必修改代码在服务端处理数据,不要将原始的内容返回给小程序)

我们先通过浏览器测试下这段代码是否生效。再次访问https://你申请的域名,如果看到类似下面的内容,则代表服务器已经配置正确。

1541148529853

这里报错很正常,因为我们没有将code参数通过浏览器传入我们搭建的微信服务器,所以会报错。接下来,我们通过小程序去请求,看看会发生什么。

获取appid和session_key

现在,请打开你微信开发者工具,点击第一步我们编写好的代码环境中的请求登录按钮,看看会发生什么。

1541148957224

系统会在微信小程序的界面自动返回当前开发者微信的openid,这个openid是唯一的,每个微信用户获取到的都不同,通过openid,我们就可以判断当前用户是否注册了你的小程序上面的业务。现在点击开发者工具控制台中的Nerwork按钮,我们看看刚才的请求是否成功。

1541149329853

我们看到,系统发送了一个HTTP请求到https://weixin.techeek.cn,然后我们点击这个域名,看看到底返回了什么样子的数据。

1541149428597

我们看到,服务器返回了openid和当前code下的session_key

总结

本文详细介绍了小程序登录鉴权的流程,后续如何存储openidsession_key这块是业务逻辑,本文暂不涉及。session_key主要用户后续解密小程序提供的开放数据,后续文章中我们将对这部分做详细介绍,并提供相关Demo做演示。喜欢的小伙伴请持续关注本专栏。腾讯云联合小程序给大家带来了小程序·云开发解决方案,为开发者提供完整的云端支持,弱化后端和运维操作,使用平台原生 API 进行核心业务开发,实现快速上线和迭代。欢迎免费使用!

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏韩伟的专栏

集群开源软件赏:ZooKeeper

本篇是开源软件最后一篇,接下来的一周将推送语言相关或项目管理相关内容。敬请期待。以下正文: 所谓集群系统,是指由多个进程和服务器合作组成完成一定功能的系统。之所...

45870
来自专栏龙首琴剑庐

原 微服务Spring Cloud Eur

24750
来自专栏后端技术探索

nginx 缓存策略实现方案

由于本人工作原因,涉及到网络直播领域,其中视频的回放下载,涉及到了一些视频下载方面的技术。针对于一个完整视频的下载,目前市面上的主流做法是,先将整个视频流切片,...

44610
来自专栏程序员宝库

从 0 到 1 优雅的实现PHP多进程管理

_ | | _ __ __ _ _ __ _ _| |_ ___ | '_...

487110
来自专栏JAVA高级架构开发

浅谈Nginx服务器的内部核心架构设计!

Nginx---Ngine X,是一款免费的、自由的、开源的、高性能HTTP服务器和反向代理服务器;也是一个IMAP、POP3、SMTP代理服务器;Nginx以...

37100
来自专栏强仔仔

Redis集群环境中添加和删除节点

上一节中说道如何在window下面安装redis集群,今天给大家介绍一下如何在redis集群环境中添加和删除节点。 首先是配置六个节点,三个为从节点,三个为主节...

33480
来自专栏零基础使用Django2.0.1打造在线教育网站

利用Flask搭建微电影视频网站(四):后台页面搭建

努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!

70510
来自专栏Flutter&Dart

DartVM服务器开发(第八天)--http服务端框架

Aqueduct是一个HTTP Web服务器框架,用于构建用Dart编写的REST应用程序。

52940
来自专栏码神联盟

碎片化 | 第四阶段-53-hibernate持久化session问题解决-视频

如清晰度低,可转PC网页观看高清版本: http://v.qq.com/x/page/h0568t95mz4.html Hibernate特性 延迟加载 做一...

30870
来自专栏三丰SanFeng

分布式系统组件之配置中心

配置中心概述: 在分布式系统中,配置中心是一个基本的组件,它为散布在不同机器上的服务提供配置文件的通知,读取,更新服务,一般对配置中心的设计要点如下: 1) 配...

215100

扫码关注云+社区

领取腾讯云代金券