如何在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. thinkphp5 模型表关联

    student 表 外键 grade_idgrade 表主键 id在 模型中student表关联方法public function Grade(){ return $this->hasOne(' ...

  2. MongoDB 学习笔记之 删除数据,集合,数据库

    删除数据,集合,数据库: 删除一个文档: db.media.deleteOne({"name": "Sky"}) 删除多个文档: db.media.delete ...

  3. Kafka 学习笔记之 Topic日志清理

    Topic日志清理 server.properties: log.cleanup.policy=delete (默认) 1. 按时间维度进行Kafka日志清理 log.retention.hours= ...

  4. Node.js入门教程 第三篇 (模块及路由)

    Node.js的模块 Node.js的模块与传统面向对象的类(class)不完全相同.Node.js认为文件即模块,即一个文件是一个模块.单一文件一般只专注做一件事情,保证了代码的简洁性. 创建模块: ...

  5. 详述Python序列化

    一.前言 1. 现实需求 每种编程语言都有各自的数据类型,其中面向对象的编程语言还允许开发者自定义数据类型(如:自定义类),Python也是一样.很多时候我们会有这样的需求: 把内存中的各种数据类型的 ...

  6. 我最推荐的一张Java后端学习路线图,Java工程师必备

    前言 学习路线图往往是学习一样技术的入门指南.网上搜到的Java学习路线图也是一抓一大把. 今天我只选一张图,仅此一图,足以包罗Java后端技术的知识点.所谓不求最好,但求最全,学习Java后端的同学 ...

  7. 面试官,不要再问我“Java GC垃圾回收机制”了

    Java GC垃圾回收几乎是面试必问的JVM问题之一,本篇文章带领大家了解Java GC的底层原理,图文并茂,突破学习及面试瓶颈. 楔子-JVM内存结构补充 在上篇<JVM之内存结构详解> ...

  8. procdump64+mimikatz获取win用户hash密码

    1.导出lsass.exe procdump64.exe -accepteula -ma lsass.exe lsass.dmp 2.执行mimikatz mimikatz.exe "sek ...

  9. MYSQL中HEX、UNHEX函数

    HEX()函数:返回十六进制值的字符串表示形式.注意:并不是十进制转化为十六进制数,而是转化为字符串... UNHEX() 函数: 每对十六进制数字转化为一个字符. 下面是HEX()几个简单的例子: ...

  10. [JZOJ5863] 【NOIP2018模拟9.11】移动光标

    Description