如何在iOS上通过电子邮件进行无缝的“无密码”身份验证。

Apple平台上的邮件和日历集成

在macOS和iOS上查看电子邮件时,邮件会在[检测到的日期和时间]下划线 。您可以与他们互动以创建新的日历事件。如果您在“日历”中打开此类活动,则会在其扩展详细信息中看到“在邮件中显示”链接。单击此链接可将您带回到原始电子邮件。此功能可以追溯到iPhone的发布。它将被纳入当年的 [Mac OS X版本(Leopard)中,] 这将标志着许多移动功能中的第一个进入台式机。

如果要将“魔术” URL复制到粘贴板并在文本编辑器中查看,则会看到以下内容:

"message:%3C1572873882024.NSHIPSTER%40mail.example.com%3E"

经验丰富的iOS开发人员将立即意识到使用 [自定义URL方案]。其中精通网络的用户可以对主机进行百分比解码,并识别出它类似于电子邮件地址,但事实并非如此。

因此,如果没有电子邮件地址,我们在这里看什么?
这是另一个不同的电子邮件字段,称为Message-ID

另外,如果你想一起进阶,不妨添加一下交流群[1012951431],选择加入一起交流,一起学习。期待你的加入!(进群可领取学习礼包)

消息ID

[RFC 5322§3.6.4]规定,每封电子邮件应该 具有“消息ID:”字段包含单个唯一消息标识符。该标识符的语法本质上是一个带有尖括号(< >)的电子邮件地址。

尽管该规范未包含任何有关生成良好Message-ID的规范性指导,但 1998年的[IETF草案草稿]还是很不错的。

让我们看一下如何在Swift中执行此操作:

生成随机消息ID

前述文档中描述的第一种技术涉及生成带有64位随机数的随机消息ID,该消息ID带有时间戳,以进一步减少冲突的机会。我们可以使用Swift 5内置的随机数生成器API和[String(_:radix:uppercase:)初始化]程序来轻松完成此操作 :

import Foundation

let timestamp = String(Int(Date().timeIntervalSince1970 * ))
let nonce = String(UInt64.random(..<UInt64.max), radix: , uppercase: true)
let domain = "mail.example.com"

let MessageID = "<\(timestamp).\(nonce)@\(domain)>"
//"<1572873882024.NSHIPSTER@mail.example.com>"

然后,我们可以将生成的Message-ID与关联的记录一起保存,以便以后链接到它。但是,在许多情况下,一种更简单的选择是使消息ID具有确定性,并且可以从其现有状态进行计算。

生成确定性消息ID

考虑符合[Identifiable协议]且其关联`ID`类型为 [UUID]的记录结构 。您可以这样生成消息ID:

import Foundation

func messageID<Value>(for value: Value, domain: String) -> String
where Value: Identifiable, Value.ID == UUID
{
return "<\(value.id.uuidString)@\(domain)>"
}

如果缺少持久性标识符(或任何其他区别功能),则可以改用消息正文本身的摘要来生成消息ID。这是使用新的[CryptoKit框架]的示例实现 :

import Foundation
import CryptoKit

let body = #"""
Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
"""#

let digest = Data(SHA256.hash(data: body.data(using: .utf8)!))
.map { String($, radix: , uppercase: true) }
.joined()

let domain = "ADF"
"<\(digest)@\(domain)>"
// "<F52380112175FCE8ECF2731C193EB8A7CC8642E53C68D292CD88531D42F145@mail.example.com>"

移动深层链接

iOS和macOS上的常规Mail客户端都将尝试`message:`通过启动到前台并尝试使用编码的Message-ID字段打开消息来使用自定义方案打开URL 。

生成具有消息ID的邮件深层链接

掌握了Message-ID之后,最后的任务是创建一个深层链接,您可以使用该深层链接将Mail打开到关联的消息。唯一的技巧是 在URL中对消息ID 进行 [百分比编码]。您可以使用[方法]来执行此操作 ,但是我们更愿意将所有操作委托给-这具有进一步的优势,即无需使用[格式字符串]就可以完整构建URL 。[`adding PercentEncoding(withAllowedCharacters:)`][`URLComponents`]

import Foundation

var components = URLComponents()
components.scheme = "message"
components.host = MessageID
components.string!
// "message://%3C1572873882024.NSHIPSTER%40mail.example.com%3E"

据我们所知,自定义`message:`方案后是否存在双斜杠不会对邮件深层链接解析产生任何影响。

打开邮件深层链接

如果您`message:`在iOS上打开URL,并且可以从 其中一个帐户的inbox轻松访问链接的消息,则Mail将立即启动该消息。如果找不到该消息,则该应用程序将启动并在后台异步加载该消息,并在可用时将其打开。相比之下,尝试在macOS上打开到尚未加载的邮件的邮件深层链接会导致显示警报模式。因此,我们建议仅在iOS上使用邮件深层链接。例如, [飞行学校]使用无密码身份验证系统来执行此操作。要访问书籍的电子副本,请输入用于购买书籍的电子邮件地址。提交表单后,iOS上的用户将看到一个深层链接,用于打开指向包含“魔术登录链接”✨的电子邮件的Mail应用程序。

其他系统可能使用消息ID通过[通用链接]简化其本机应用或网站的无密码身份验证 ,或者将其合并为2fa策略的一部分 (因为[出于此目的,不再认为][sms是安全的])。如果您在Web应用程序中使用Rails,则 [ActiveMailer拦截器]提供了一种方便的方式来Message-ID为无密码验证流注入字段。


与苹果平台上如此众多的私人集成(仍然是第一方应用程序的专有领域)不同,“在邮件中显示”的秘密之处在于我们所有人都能参与进来。尽管没有记录,但是由于该功能与系统的深度集成以及植根于基本Web标准中,因此该功能不太可能很快被删除。

从[浏览器供应商], [社交媒体公司]到 [政府](甚至有时甚至是苹果[公司)的]每个人都 试图拆开开放的网络并控制我们可以看到和执行的操作时,很高兴得知电子邮件 [将近50年了],保持互联网自由和分散的能力仍然坚决。

翻译地址: https://nshipster.com/message-id/

iOS和macOS上的Message-ID和Mail.app深度链接的更多相关文章

  1. 保护 iOS 用户数据安全: Keychain 和 Touch ID

    原文:How To Secure iOS User Data: The Keychain and Touch ID 作者:Tim Mitra 译者:kmyhy 更新说明:本教程由 Tim Mitra ...

  2. 苹果系统iOS、macOS应用管理机制

    iOS.macOS系统应用管理机制 苹果系统包括:iOS.macOS.watchOS.tvOS.应用软件的生命周期为:开发.上线.安装.使用.卸载.这篇文档将从应用生命周期的各个环节介绍苹果系统对应用 ...

  3. ios学习之 关于Certificate、Provisioning Profile、App ID的介绍及其之间的关系

    刚接触iOS开发的人难免会对苹果的各种证书.配置文件等不甚了解,可能你按照网上的教程一步一步的成功申请了真机调试,但是还是对其中的缘由一知半解.这篇文章就对Certificate.Provisioni ...

  4. (转) ios学习之 关于Certificate、Provisioning Profile、App ID的介绍及其之间的关系

    刚接触iOS开发的人难免会对苹果的各种证书.配置文件等不甚了解,可能你按照网上的教程一步一步的成功申请了真机调试,但是还是对其中的缘由一知半解.这篇文章就对Certificate.Provisioni ...

  5. Cocos2D在Xcode7和iOS 9.2上IMP调用出错

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 原来的代码一直在Xcode6.4上和iOS 8.4上运行,没有 ...

  6. iOS多图上传

    iOS多图上传涉及到多线程问题,个人比较喜欢使用GCD操作,下边是最近写的一个多图上传代码,附带相关注释 __block BOOL allSucc = YES; __block int m = 0; ...

  7. IOS 视频.图片上传服务器

    //上传视频 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];    manager.requestSerializer. ...

  8. iOS 10 中引入了 Message 框架

    WWDC 2016 上最重磅的消息之一就是在 iOS 10 中引入了 Message 框架.开发者现在可以为苹果内置的 Messages 应用开发扩展啦.通过开发一个应用扩展,你可以让用户跟应用在 M ...

  9. [App Store Connect帮助]八、维护您的 App(4.3)回复顾客评论(iOS、macOS 或 watchOS)

    您可以公开回复顾客评论,但在您的 App Store 产品页上每条评论仅会显示一条回复.您可以回复评论.编辑回复,以及删除回复. 在回复和编辑显示在 App Store 上之前(可能需要至多 24 小 ...

随机推荐

  1. Java后台开发方向面试题集合

    内容会不断更新. 初衷是每次看面经肯定都会有一些一时反应不过来的问题,希望集中记录一下便于自己查看. 而答案部分谷歌就很好,当然有些问题可能需要多次谷歌. 对于一些记不住的答案,我也会持续写上一些. ...

  2. ELK 学习笔记之 Kibana入门使用

    Kibana入门使用: 第一次导入索引: 修改展示时间,不然查不到数据: 点Discover,查阅数据: 如果要添加新的index: 点击Visualize, 创建chart: 点击Dashboard ...

  3. 用OllyDbg爆破一个小程序

    用OllyDbg爆破一个小程序 一.TraceMe小程序 TraceMe是对用户名.序列号判断是否合法的一个小程序.我们任意输入一组用户名.序列号进行check判断,结果如下: 二.用OllyDbg对 ...

  4. smp_processor_id()获取当前执行cpu_id

    基于Linux 2.6.32内核进行分析,看本篇文章前,建议先看看percpu变量这篇文章 smp_processor_id()用来获取当前cpu的id,首先来看smp_processor_id的定义 ...

  5. python编程基础之二十七

    列表生成式:[exp for iter_var in iterable] 同样也会有字典生成式,集合生成式,没有元组生成式,元组生成式的语法被占用了 字典生成式,集合生成式,就是外面那个括号换成{}  ...

  6. 利用 turtle库绘制简单图形

    turtle库是python的基础绘图库,这个库被介绍为一个最常用的用来介绍编程知识的方法库,其主要是用于程序设计入门,是标准库之一,利用turtle可以制作很多复杂的绘图. turtle名称含义为“ ...

  7. Flask的路由解读以及其配置

    from flask import Flask app =Flask(__name__) 一.配置 配置一共有四中方式 方法一: 只能设置以下两种属性 app.debug=True app.secre ...

  8. shark恒破解笔记2-绕过自校验

    这集讲的是绕过自校验 主要是通过文件大小的自校验 首先查壳 有壳  可以用esp定律搞定 OD载入  右键od脱裤壳调试进程 可以看到一些信息 包括入口点252F0 修正后地址为252F0 loadP ...

  9. PowerShell渗透--Empire

    0x00 简介 Empire是一款针对Windows平台的,使用PowerShell脚本作为攻击载荷的渗透攻击框架代码具有从stager生成,提权到渗透维持的一系列功能,无需powershell.ex ...

  10. 分布式FastDFS集群部署

    FastDFS FastDFS的作者余庆在其 GitHub 上是这样描述的:"FastDFS is an open source high performance distributed f ...