Day978.如何在移动App中使用OAuth 2.0? -OAuth 2.0

news2024/12/24 9:58:54

如何在移动App中使用OAuth 2.0?

Hi,我是阿昌,今天学习记录的是关于如何在移动App中使用OAuth 2.0?的内容。

除了 Web 应用外,现实环境中还有非常多的移动 App

那么,在移动 App 中,能不能使用 OAuth 2.0 ,又该如何使用 OAuth 2.0 呢?

没错,OAuth 2.0 最初的应用场景确实是 Web 应用,但是它的伟大之处就在于,它把自己的核心协议定位成了一个框架而不是单个的协议。这样做的好处是,可以基于这个基本的框架协议,在一些特定的领域进行扩展。

因此,到了桌面或者移动的场景下,OAuth 2.0 的协议一样适用。考虑到授权码许可是最完备、最安全的许可类型,在移动 App 如何使用 OAuth 2.0 的时候,依然会用授权码许可来讲解,毕竟“要用就用最好的”。


当开发一款移动 App 的时候,可以选择没有 Server 端的 “纯 App” 架构,比如这款 App 不需要跟自己的 Server 端通信,或者可以调用其它开放的 HTTP 接口;

当然也可以选择有服务端的架构,比如这款 App 还想把用户的操作日志记录下来并保存到 Server 端的数据库中。

那总结下来呢,移动 App 可以分为两类

  • 一类是没有 Server 端的 App 应用
  • 一类是有 Server 端的 App 应用。

图1 两类移动App

这两类 App 在使用 OAuth 2.0 时的最大区别,在于获取访问令牌的方式

  • 如果有 Server 端,就建议通过 Server 端和授权服务做交互来换取访问令牌
  • 如果没有 Server 端,那么只能通过前端通信来跟授权服务做交互,比如隐式许可授权类型。当然,这种方式的安全性就降低了很多。

有些时候,可能觉得自己开发一个 App 不需要一个 Server 端。

那好,就让先来看看没有 Server 端的 App 应用如何使用授权码许可类型。


一、没有 Server 端的 App

在一个没有 Server 端支持的纯 App 应用中,首先想到的是,如何可以像 Web 服务那样,让请求和响应“来去自如”呢。

是不是可以将一个“迷你”的 Web 服务器嵌入到 App 里面去,这样不就可以像 Web 应用那样来使用 OAuth 2.0 了么?确实,这是行得通的,而且已经有 App 这样做了。

这样的 App 通过监听运行在 localhost 上的 Web 服务器 URI,就可以做到跟普通的 Web 应用一样的通信机制,但这种方式不是这次要讲的重点。

因为当使用这种方式的时候,请求访问令牌时需要的 app_secret 就只能保存在用户本地设备上,而这并不是所建议的。

到这里,问题的关键在于如何保存 app_secret,因为 App 会被安装在成千上万个终端设备上,app_secret 一旦被破解,就将会造成灾难性的后果。

这时,有的同学突发奇想,如果不用 app_secret,也能在授权码流程里换回访问令牌 access_token,不就可以了吗?但新的问题也来了。

在授权码许可类型的流程中,如果没有了 app_secret 这一层的保护,那么通过授权码 code 换取访问令牌的时候,就只有授权码 code 在“冲锋陷阵”了。授权码 code 一旦失窃,就会带来严重的安全问题。

那么,既不使用 app_secret,还要防止授权码 code 失窃,有什么好的方法吗?

有,OAuth 2.0 里面就有这样的指导方法。这个方法就是 PKCE 协议,全称是 Proof Key for Code Exchange by OAuth Public Clients。

在下面的流程图中,为了突出第三方软件使用 PKCE 协议时与授权服务之间的通信过程,省略了受保护资源服务和资源拥有者的角色:

图2 使用PKCE协议的流程图

首先,App 自己要生成一个随机的、长度在 43~128 字符之间的、参数为 code_verifier 的字符串验证码;

接着,再利用这个 code_verifier,来生成一个被称为“挑战码”的参数code_challenge。那怎么生成这个 code_challenge 的值呢?

OAuth 2.0 规范里面给出了两种方法,就是看 code_challenge_method 这个参数的值:

  • 一种 code_challenge_method=plain,此时 code_verifier 的值就是 code_challenge 的值;
  • 另外一种 code_challenge_method=S256,就是将 code_verifier 值进行 ASCII 编码之后再进行哈希,然后再将哈希之后的值进行 BASE64-URL 编码,如下代码所示。
code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))

好了,知道有这样两个值,也知道它们的生成方法了,但这两个值跟我们的授权码流程有什么关系呢,又怎么利用它们呢?

授权码流程简单概括起来不是有两步吗,第一步是获取授权码 code,第二步是用 app_id+app_secret+code 获取访问令牌 access_token。

刚才“梦想”不是设想不使用 app_secret,但同时又能保证授权码流程的安全性么?没错。

code_verifier 和 code_challenge 这两个参数,就是来帮实现这个“梦想”的。

在第一步获取授权码 code 的时候,使用 code_challenge 参数。

需要注意的是,要同时将 code_challenge_method 参数也传过去,目的是让授权服务知道生成 code_challenge 值的方法是 plain 还是 S256。

https://authorization-server.com/auth?
response_type=code&
app_id=APP_ID&
redirect_uri=REDIRECT_URI&
code_challenge=CODE_CHALLENGE&
code_challenge_method=S256

在第二步获取访问令牌的时候,使用 code_verifier 参数,授权服务此时会将 code_verifier 的值进行一次运算。

那怎么运算呢?就是上面 code_challenge_method=S256 的这种方式。

没错,第一步请求授权码的时候,已经告诉授权服务生成 code_challenge 的方法了。

所以,在第二步的过程中,授权服务将运算的值跟第一步接收到的值做比较,如果相同就颁发访问令牌。

POST https://api.authorization-server.com/token?
  grant_type=authorization_code&
  code=AUTH_CODE_HERE&
  redirect_uri=REDIRECT_URI&
  app_id=APP_ID&
  code_verifier=CODE_VERIFIER

现在,就知道了是如何使用 code_verifier 和 code_challenge 这两个参数的了吧。

总结一下就是,换取授权码 code 的时候,使用 code_challenge 参数值;换取访问令牌的时候,使用 code_verifier 参数值。

为什么要这样做呢。愿望是,没有 Server 端的手机 App,也可以使用授权码许可流程,对吧?

app_secret 不能用,因为它只能被存在用户的设备上,担心被泄露。

那么,在没有了 app_secret 这层保护的前提下,即使授权码 code 被截获,再加上 code_challenge 也同时被截获了,那也没有办法由 code_challenge 逆推出 code_verifier 的值。而恰恰在第二步换取访问令牌的时候,授权服务需要的就是 code_verifier 的值。

因此,这也就避免了访问令牌被恶意换取的安全问题。现在,可以通过 PKCE 协议的帮助,让没有 Server 端的 App 也能够安全地使用授权码许可类型进行授权了。

按照 OAuth 2.0 的规范建议,通过后端通信来换取访问令牌是较为安全的方式。

在做移动应用开发的时候,真的从设计上就决定废弃 Server 端了吗?


二、有 Server 端的 App

如果开发接入过微信登录,就会在微信的官方文档上看到下面这句话:

微信 OAuth 2.0 授权登录目前支持 authorization_code 模式,适用于拥有 Server 端的应用授权。

没错,微信的 OAuth 2.0 授权登录,就是建议需要一个 Server 端来支持这样的授权接入。

那么,有 Server 端支持的 App 又是如何使用 OAuth 2.0 的授权码许可流程的呢?

仍以微信登录为例,看一下官方的流程图:

在这里插入图片描述

看到这个图,是不是觉得特别熟悉,跟普通的授权码流程没有区别,仍是两步走的策略:

  • 第一步换取授权码 code
  • 第二步通过授权码 code 换取访问令牌 access_token。

这里的第三方应用,就是我们作为开发者来开发的应用,包含了移动 App 和 Server 端。

将其“放大”得到下面这张图:

图4 有Server端的App的授权流程

从这张“放大”的图中,就会发现有 Server 端的 App 在使用授权码流程的时候,跟普通的 Web 应用几乎没有任何差别

  1. 大概流程是:当访问第三方 App 的时候,需要用到微信来登录;
  2. 第三方 App 可以拉起微信的 App,会在微信的 App 里面进行登录及授权;
  3. 微信 Server 端验证成功之后会返回一个授权码 code,通过微信 App 传递给了第三方 App;
  4. 后面的流程就是熟悉的使用授权码 code 和 app_secret,换取访问令牌 access_token 的值了。

这次使用 app_secret 的时候,是在第三方 App 的 Server 端来使用的,因此安全性上没有任何问题。


三、总结

没有 Server 端的 App有 Server 端的 App 分别是如何使用授权码许可类型的。

  • 使用 OAuth 2.0 协议的目的,就是要起到安全性的作用,但有些时候,因为使用不当反而会造成更大的安全问题,比如将 app_secret 放入 App 中的最基本错误。如果放弃了 app_secret,又是如何让没有 Server 端的 App 安全地使用授权码许可协议呢?针对这种情况,介绍了 PKCE 协议。它是一种在失去 app_secret 保护的时候,防止授权码失窃的解决方案。
  • App 时候真的不需要一个 Server 端吗?建议你在开发移动 App 的时候,尽可能地都要搭建一个 Server 端,因为通过后端通信来传输访问令牌比通过前端通信传输要安全得多。也举了微信的例子,很多官方的开放平台在提供 OAuth 2.0 服务的时候,都会建议开发者要有一个相应的 Server 端。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/899218.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

手把手带你设计接口自动化测试用例(一):提取接口信息并分析

1、测试行业市场现状 随着市场需求的变化,大部分企业在招聘测试人员时,都会提出接口自动化测试的相关要求,为什么会这样呢? 目前,软件构架基本上都是前后端分离的,软件的主要功能由服务端提供。从整个软件…

生成国密SM2密钥对

在线生成国密密钥对 生成的密钥对要妥善保管,丢失是无法找回的。

windows无法与设备或主DNS服务器通信

今天电脑连上wifi后发现qq可以登录,爱奇艺也可以正常使用,但是就浏览器不能用,不管哪个网站都是无法访问,点击下面的Windows网络诊断后发现是因为windows无法与设备或主DNS服务器通信 1.右下角右键wifi图标,打开网络和internet设置 2.点击网络和共享中心 3. 点击更改适配器设置…

(杭电多校)2023“钉耙编程”中国大学生算法设计超级联赛(9)

1002 shortest path 记忆化搜索可以用 map 实现&#xff0c;频繁读取而不考虑元素顺序的可以使用 unordered_map &#xff0c;有效降低时间空间复杂度 dfs(n/2)n%21,其中n%2表示将n变为偶数的次数,1表示操作n/2,dfs(n/2)即表示将n/2变为1的次数 AC代码: #include<iostre…

深入探索Spring后置处理器:解析作用与实际应用场景

前言 BeanDefinitionRegistryPostProcessor &#xff0c; BeanFactoryPostProcessor &#xff0c;InstantiationAwareBeanPostProcessor&#xff0c; BeanPostProcessor是spring生命周期中常见的4个后置处理器&#xff0c;但是对于其作用和执行顺序很多人还不是非常清楚&#…

软件测试的调用接口怎么调用,逻辑是什么?

一、什么是接口测试&#xff1f; 接口测试是测试系统组件之间接口的测试。接口主要用于检测外部系统和内部子系统之间的交互点。测试的重点是检查数据交换、传输、控制和管理过程&#xff0c;以及系统之间的相互逻辑依赖。 二、为什么要做接口测试&#xff1f; 在淘宝系统的…

Java8新特性---Stream流

什么是Stream 是数据渠道&#xff0c;用于操作数据源&#xff08;集合、数组等&#xff09;所生成的元素序列。集合讲究的是数据&#xff0c;流讲的是计算 注意&#xff1a; Stream不会自己存储元素Stream不会改变源对象&#xff0c;相反&#xff0c;他们会返回持有结果的新…

GPT-4耗尽全宇宙数据!OpenAI接连吃官司,竟因数据太缺了,UC伯克利教授发出警告

穷尽「全网」&#xff0c;生成式AI很快无数据可用。 近日&#xff0c;著名UC伯克利计算机科学家Stuart Russell称&#xff0c;ChatGPT和其他AI工具的训练可能很快耗尽「全宇宙的文本」。 换句话说&#xff0c;训练像ChatGPT这样的AI&#xff0c;将因数据量不够而受阻。 这可能…

五、修改官方FreeRTOS例程(STM32F1)

1、官方源码下载 (1)进入FreeRTOS官网&#xff1a;FreeRTOS官网 (2)下载FreeRTOS。(选择带示例的下载) 2、删减目录 (1)下载后解压的FreeRTOS文件如下图所示。 (2)删除下图中红框勾选的文件。 FreeRTOS-Plus&#xff0c;FreeRTOS的生态文件&#xff0c;非必需的。tools&…

esp8266+电压检测模块检测电池电压

该模块5v时输出1v&#xff0c;因esp8266 ADC引脚(A0)支持电压范围是0v-1v&#xff0c;所以该方案仅支持0-5v电压检测 接线&#xff1a; - 接 esp8266GND 可不接 S 接 ADC esp8266 为 A0 VCC 被检测直流电 GND 被检测直流电- #include <Wire.h>const int adcPin A0; // …

Redis五大基本数据类型及其使用场景

文章目录 **一 什么是NoSQL&#xff1f;****二 redis是什么&#xff1f;****三 redis五大基本类型**1 String&#xff08;字符串&#xff09;**应用场景** 2 List&#xff08;列表&#xff09;**应用场景** 3 Set&#xff08;集合&#xff09;4 sorted set&#xff08;有序集合…

excel逻辑函数篇1

1、AND(logical1,[logical2],…)&#xff1a;用于测试所有条件是否均为TRUE 检查所有参数均为true&#xff0c;如果是则返回true 2、OR(logical1,[logical2],…)&#xff1a;用于测试是否有为TRUE的条件 如果任意参数值为true&#xff0c;即返回true&#xff1b;只有当所有参数…

223、仿真-基于51单片机温湿度PH值二氧化碳(C02)报警Proteus仿真设计(程序+Proteus仿真+配套资料等)

毕设帮助、开题指导、技术解答(有偿)见文未 目录 一、硬件设计 二、设计功能 三、Proteus仿真图 四、程序源码 资料包括&#xff1a; 需要完整的资料可以点击下面的名片加下我&#xff0c;找我要资源压缩包的百度网盘下载地址及提取码。 方案选择 单片机的选择 方案一&…

机器学习笔记 - 基于keras + 小型Xception网络进行图像分类

一、简述 Xception 是深度为 71 层的卷积神经网络,仅依赖于深度可分离的卷积层。 论文中将卷积神经网络中的 Inception 模块解释为常规卷积和深度可分离卷积运算(深度卷积后跟点卷积)之间的中间步骤。从这个角度来看,深度可分离卷积可以理解为具有最大数量塔的 Inception 模…

学习笔记230804---restful风格的接口,delete的传参方式问题

如果后端提供的删除接口是restful风格&#xff0c;那么使用地址栏拼接的方式发送请求&#xff0c;数据放在主体中&#xff0c;后端接受不到&#xff0c;当然也还有一种可能&#xff0c;后端在这个接口的接参设置上是req.query接参。 问题描述 今天遇到的问题是&#xff0c;de…

windows子系统wsl2备份(迁移D盘)还原系统

windows子系统wsl2备份还原系统 1.查看wsl版本 wsl -l -v2.停止wsl子系统 wsl --terminate Ubuntu-22.043.导出子系统备份 wsl --export Ubuntu-22.04 D:\Ubuntu_bak.tar4.删除原有系统 wsl --unregister Ubuntu-22.045.还原系统 wsl --import Ubuntu-22.04 d:\Ubuntu-ws…

Jenkins-发送邮件配置

在Jenkins构建执行完毕后&#xff0c;需要及时通知相关人员。因此在jenkins中是可以通过邮件通知的。 一、Jenkins自带的邮件通知功能 找到manage Jenkins->Configure System&#xff0c;进行邮件配置&#xff1a; 2. 配置Jenkins自带的邮箱信息 完成上面的配置后&#xf…

【0基础入门Python笔记】三、python 之函数以及常用内置函数

三、python 之函数以及常用内置函数 函数函数定义函数调用函数参数返回值 常用内置函数input()函数range()函数其它 函数 函数是一种用于封装可重复使用代码块的工具&#xff0c;能够将一系列操作组织成一个逻辑单元。 函数定义 在Python中&#xff0c;函数通过def关键字进行…

Python可视化在量化交易中的应用(12)_Seaborn柱状图

Seaborn中柱状图的绘制方法 seaborn中绘制折线图使用的是sns.barplot()函数&#xff1a; sns.barplot(x,y,hue,data,order,hue_order,estimator,ci95,n_boot1000,units,seed,orient,color,palette,saturation0.75,errcolor‘.26’,errwidth,capsize,dodgeTrue,ax,**kwargs,) …

linux RabbitMQ-3.8.5 安装

软件版本操作系统CentOS Linux release 7.9.2009erlangerlang-23.0.2-1.el7.x86_64rabbitMQrabbitmq-server-3.8.5-1.el7 RabbitMQ的安装首先需要安装Erlang,因为它是基于Erlang的VM运行的。 RabbitMQ安装需要依赖:socat和logrotate&#xff0c;logrotate操作系统已经存在了&…