热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Force.com微信开发系列(七)OAuth2.0网页授权

OAuth是一个开放协议,允许用户让第三方应用以安全且标准的方式获取该用户在某一网站上存储的私密资源(如用户个人信息、照片、视频、联系人列表),而无须将用户名和密码提供给第三方应用。本文将详细介绍OA

OAuth是一个开放协议,允许用户让第三方应用以安全且标准的方式获取该用户在某一网站上存储的私密资源(如用户个人信息、照片、视频、联系人列表),而无须将用户名和密码提供给第三方应用。本文将详细介绍OAuth协议以及在微信里的具体实现。

 

OAuth2.0协议介绍

OAuth2.0是OAuth协议的下一版本,但不向后兼容OAuth 1.0。 OAuth 2.0关注客户端开发者的简易性,同时为Web应用,桌面应用和手机,和起居室设备提供专门的认证流程。 OAuth2.0允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要分享他们的访问许可或他们数据的所有内容。

 

OAuth2.0认证和授权的具体过程:

在Oauth2.0认证和授权的过程中涉及的三方包括:

1. 服务提供方,用户使用服务提供方来存储受保护的资源,如照片,视频,联系人列表。

2. 用户,存放在服务提供方的受保护的资源的拥有者。

3. 客户端,要访问服务提供方资源的第三方应用,通常是网站,如提供照片打印服务的网站。在认证过程之前,客户端要向服务提供者申请客户端标识。

 

使用OAuth进行认证和授权的过程如下所示:

1. 用户访问客户端的网站,想操作用户存放在服务提供方的资源;

2. 客户端向服务提供方请求一个临时令牌;

3. 服务提供方验证客户端的身份后,授予一个临时令牌;

4. 客户端获得临时令牌后,将用户引导至服务提供方的授权页面请求用户授权。在这个过程中将临时令牌和客户端的回调连接发送给服务提供方;

5. 用户在服务提供方的网页上输入用户名和密码,然后授权该客户端访问所请求的资源;

6. 授权成功后,服务提供方引导用户返回客户端的网页;

7. 客户端根据临时令牌从服务提供方那里获取访问令牌;

8. 服务提供方根据临时令牌和用户的授权情况授予客户端访问令牌;

9. 客户端使用获取的访问令牌访问存放在服务提供方上的受保护的资源。


微信网页OAuth2.0授权:

如果用户在微信中(Web微信除外)访问公众号的第三方网页,公众号开发者可以通过此接口获取当前用户基本信息(包括昵称、性别、城市、国家)。利用用户信息,可以实现体验优化、用户来源统计、帐号绑定、用户身份鉴权等功能。

需要注意的是,获取用户基本信息接口(稍后博文会介绍到)是在用户和公众号产生消息交互时,才能根据用户OpenID获取用户基本信息,而网页授权的方式获取用户基本信息,则无需消息交互,只是用户进入到公众号的网页,就可弹出请求用户授权的界面,用户授权后,就可获得其基本信息(此过程甚至不需要用户已经关注公众号。)

下面我们将通过一个具体的例子来展示开发的详细过程。

 

 

配置授权回调域名:

 

在微信公众号请求用户网页授权之前,开发者需要先到公众平台网站的我的服务页中配置授权回调名,需要注意的是这里的域名不要加http://或者https://。另外,授权回调域名配置规范为全域名,比如需要网页授权的域名为:www.qq.com,配置以后此域名下的所有页面例如http://www.qq.com/music.html, http://www.qq.com/login.html都可以进行OAuth2.0鉴权。但http://pay.qq.com, http://music.qq.com无法进行OAuth2.0鉴权。

为此进入到服务页(使用正式的服务号或认证后的订阅号后通过我的服务找到,如果是测试账号直接在首页即可找到)后找到OAuth2.0网页授权,点击右侧的修改链接:

image

 

 

在弹出窗口里输入域名后点击确定按钮保存:

image

 

用户同意授权,获取Code:

此步骤相当于前面介绍到的OAuth2.0认证过程的第二步“客户端向服务提供方请求一个临时令牌”,这里的Code即是临时令牌,为此可以请求微信的OAuth2.0接口以获取该Code,该接口的参数里需要指定一个回调页面URL,为此我们需要创建一个Apex Page,为此登陆Force.com后找到域名,通常从中国访问的域名是https://ap1.salesforce.com, 在浏览器地址栏中输入https://ap1.salesforce.com/apex/oauth2test, 此时Force.com将提示页面不存在,点击“Create Page oauth2test”链接创建页面:

 

image

 

创建好后的页面如下,如果启用了开发者模式,则页面分为上下两个部分,上部分是显示效果,下面是源代码编辑窗口,默认Force.com会将自身的顶部导航、左侧导航以及CSS样式应用到新创建的页面:

image

 

我们通过在第一行里加入以下代码告诉Force.com不要使用默认的CSS样式,不要显示顶部以及左侧的导航栏,同时最后一个controller属性指定了apex页面对应的控制器类,类似于aspx页面对应的aspx.cs类,鼠标保持在编辑栏窗口,按住Ctrl + S组合键即可保存编辑后的代码:

 

此时,应为对应的oauth2testcontroller类并不存在,浏览器会报以下错误:

image

 

这里点击第二个链接“Create Apex class ‘public class oauth2testcontroller’”自动创建控制器类。留意这两个链接的唯一区别在于”with sharing”关键字,这个关键字指定了当前类对各个对对象(相当于数据表)、字段等的访问权限与当前登录用户同,如果不指定,Apex页面将拥有对所有对象、字段的访问权限。创建好后在下方代码编辑栏中将多出一个控制器类Tab:

 

image

 

在该类中添加代码如下:

1 public class oauth2testcontroller { 
2     public String code {get; set;} 
3     public oauth2testcontroller(){ 
4         code = ApexPages.currentPage().getParameters().get('code'); 
5         if(String.isBlank(code)){ 
6             code = 'No Code'; 
7         } 
8     } 
9 }

 

这段代码中第2行定义了一个公开属性code,第4行通过ApexPages对象获得URL中的code参数,并接着判断是否code值是否为空,如果为空则提示No Code。下面我们会看到微信授权成功回调此URL时会将code参数添加到URL中。

接下来略微修改前台页面,在页面中显示得到的code值:

1 "false" showHeader="false" sidebar="false" cOntroller="oauth2testcontroller"> 
2     {!code} 
3 

 

{!对象名}是Force.com Visualforce page里用来显示对象值的语法,接下来我们需要配置该页面能够通过公网进行访问,为此登陆Force.com后,进入Setup –> Develop –> Sites,点击站点对应的Site Label标签如下图:

image

进入详细配置页面后找到“Site Visualforce Page”,点击右侧的Edit按钮:

image

找到左侧列表中的oauth2test页面添加到右侧,并保存修改:

image

 

此时即可通过http://johnson0001-developer-edition.ap1.force.com/oauth2test公网地址来访问前面创造的页面了。接下来我们可以利用微信平台的OAuth2认证接口组拼URL并引导用户通过微信来访问,该接口的格式如下:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限,其中每个参数的详细说明如下:

image

在我们的例子里URL如下,其中scope我们指定为snsapi_userinfo,弹出授权页面:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx3b3aef2c09447269&redirect_uri=http://johnson0001-developer-edition.ap1.force.com/oauth2test&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

兴许是测试账号的关系,虽然微信接口文档里提到在制定scope为snsapi_userinfo的情况下会弹出如下图左所示的授权页面,但反复尝试(乃至删除并重新关注账号)中也没有看到该页面,不过重点是我们得到了临时令牌,如下图右所示。右图实际是http://johnson0001-developer-edition.ap1.force.com/oauth2test页面,用户同意授权后跳转到(或者我遇到的实际情况是直接跳转)到redirect_uri/?CODE&state=STATE。若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数redirect_uri?state=STATE。

另外特别需要说明的是,code作为换取access_token的临时票据,每次用户授权带上的code都不一样,code只能使用一次,5分钟未被使用自动过期。

image                               image

 

通过Code换取网页授权access_token:

首先请注意,这里通过code换取的网页授权access_token,与基础支持中的access_token不同。公众号可通过下述接口来获取网页授权access_token。如果网页授权的作用域为snsapi_base,则本步骤中获取到网页授权access_token的同时,也获取到了 openid,snsapi_base式的网页授权流程即到此为止。 获取code后,可以通过以下接口获取access_token:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

这里的CODE即为通过前面方式获得的临时令牌(票据),参数的具体说明如下:

image

 

将URL直接输入到浏览器地址栏即可得到返回数据,当然真实场景里更多通过后台代码来请求,正确返回时的JSON数据包如下:

1 {
2    "access_token":"ACCESS_TOKEN",
3    "expires_in":7200,
4    "refresh_token":"REFRESH_TOKEN",
5    "openid":"OPENID",
6    "scope":"SCOPE"
7 }

 

参数的具体说明如下:

image

错误时微信会返回JSON数据包如下(示例为Code无效错误):

{"errcode":40029,"errmsg":"invalid code"}

 

在本例中获得的access_token实例如下:

{"access_token":"OezXcEiiBSKSxW0eoylIeMEUA_AZuBDY8AO0IIw270MMsvemqLvgx1HqemeXIZfzXW2d6yHCPy9cA1yHZ1jHCkwlH5Ct5Jfa1jOQm88M9LzU_O8BCKMNhN7yLlHJfOFLuf4lLTNGOOsoWYxQzYVNGw","expires_in":7200,"refresh_token":"OezXcEiiBSKSxW0eoylIeMEUA_AZuBDY8AO0IIw270MMsvemqLvgx1HqemeXIZfz_Vj5pJZlv2V5wK9EzWmxQmM07cqIAwMXOdqzlQs-NY4hiyENP4WhO4Twpko-3iY_pAPZRnGGmAVt3DirZaWIyg","openid":"ou-37t936RNZEcW0mI75RN2pdxkc","scope":"snsapi_userinfo"}

可以看到上面access_token的默认失效时间是7200秒,也就是2小时,当access_token超时后,可以通过refresh_token进行刷新,refresh_token拥有较长的有效期(7天、30天、60天、90天),当refresh_token失效后,需要用户重新授权,简化理解起见,我们在本文的最后再介绍相关技术。

 

拉取用户信息(需Scope为snasapi_userinfo):

通过access_token获取用户信息的接口如下,使用GET方法:

https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN

参数具体说明如下:

image

本例的URL如下:

https://api.weixin.qq.com/sns/userinfo?access_token=OezXcEiiBSKSxW0eoylIeMEUA_AZuBDY8AO0IIw270MMsvemqLvgx1HqemeXIZfzXW2d6yHCPy9cA1yHZ1jHCkwlH5Ct5Jfa1jOQm88M9LzU_O8BCKMNhN7yLlHJfOFLuf4lLTNGOOsoWYxQzYVNGw&openid=ou-37t936RNZEcW0mI75RN2pdxkc&lang=zh_CN

输入浏览器访问即可得到相应的用户信息:

1 {"openid":"ou-37t936RNZEcW0mI75RN2pdxkc","nickname":"王浩","sex":1,"language":"zh_CN","city":"松江","province":"上海","country":"中国","headimgurl":"http:\/\/wx.qlogo.cn\/mmopen\/lqsZNvDqcXe8nBKHBPsp9YHuZXPtkzOD1uq3r3xxDicuDLKGlicNd1b371ODnn9xNBB9y9ChBSfL7tuX6m9FS8koY9Ex1iaJRDI\/0","privilege":[]}

 

刷新access_token:

可以通过前面在“通过Code换取网页授权access_token”小节中获得的refresh_token来调用刷新Token接口获取更新的access_token,微信在API文档里介绍refresh_token拥有较长的有效期(7天、30天、60天、90天),但实际微信的refresh_token的有效期是多长没有具体说明,如果有具体经验的朋友欢迎分享。微信刷新access_token的接口如下:

https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN

接口的具体参数定义如下:

image

正确时返回的JSON数据包如下:

1 {
2    "access_token":"ACCESS_TOKEN",
3    "expires_in":7200,
4    "refresh_token":"REFRESH_TOKEN",
5    "openid":"OPENID",
6    "scope":"SCOPE"
7 }

 

数据包的具体定义如下:

image

错误时微信会返回JSON数据包如下(示例为Code无效错误):

{"errcode":40029,"errmsg":"invalid code"}


推荐阅读
  • ASP.NET2.0数据教程之十四:使用FormView的模板
    本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
  • MVC中的自定义控件
    怎么样创建自定义控 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 这是原文链接:sendingformdata许多情况下,我们使用表单发送数据到服务器。服务器处理数据并返回响应给用户。这看起来很简单,但是 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • web.py开发web 第八章 Formalchemy 服务端验证方法
    本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
  • Servlet多用户登录时HttpSession会话信息覆盖问题的解决方案
    本文讨论了在Servlet多用户登录时可能出现的HttpSession会话信息覆盖问题,并提供了解决方案。通过分析JSESSIONID的作用机制和编码方式,我们可以得出每个HttpSession对象都是通过客户端发送的唯一JSESSIONID来识别的,因此无需担心会话信息被覆盖的问题。需要注意的是,本文讨论的是多个客户端级别上的多用户登录,而非同一个浏览器级别上的多用户登录。 ... [详细]
  • 微信官方授权及获取OpenId的方法,服务器通过SpringBoot实现
    主要步骤:前端获取到code(wx.login),传入服务器服务器通过参数AppID和AppSecret访问官方接口,获取到OpenId ... [详细]
  • Apache Shiro 身份验证绕过漏洞 (CVE202011989) 详细解析及防范措施
    本文详细解析了Apache Shiro 身份验证绕过漏洞 (CVE202011989) 的原理和影响,并提供了相应的防范措施。Apache Shiro 是一个强大且易用的Java安全框架,常用于执行身份验证、授权、密码和会话管理。在Apache Shiro 1.5.3之前的版本中,与Spring控制器一起使用时,存在特制请求可能导致身份验证绕过的漏洞。本文还介绍了该漏洞的具体细节,并给出了防范该漏洞的建议措施。 ... [详细]
  • 本文介绍了利用ARMA模型对平稳非白噪声序列进行建模的步骤及代码实现。首先对观察值序列进行样本自相关系数和样本偏自相关系数的计算,然后根据这些系数的性质选择适当的ARMA模型进行拟合,并估计模型中的位置参数。接着进行模型的有效性检验,如果不通过则重新选择模型再拟合,如果通过则进行模型优化。最后利用拟合模型预测序列的未来走势。文章还介绍了绘制时序图、平稳性检验、白噪声检验、确定ARMA阶数和预测未来走势的代码实现。 ... [详细]
  • 在浏览器进行微信h5支付时出现:在https:pay.weixin.qq.comwikidocapiH5.php?chapter15_4官 ... [详细]
author-avatar
克乄浪木守
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有