iOS 开发之密码规则

密码规则 / UIText​Input​Password​Rules

原文

也难怪 hipster 们着迷于工艺品和手工制品。不管是一片厚切鳄梨吐司、一瓶限量(非乳制)姜黄奶或一杯完美的手冲咖啡——其中的人情味是无法替代的。

相反,好密码和工艺品截然不同。密码应该完全没有任何意义,除非它是一个 90 年代骇客电影的标题或者一个密室逃脱游戏的答案。

有了 iOS 12 和 macOS Mojave 中的 Safari,生成可以想象到的最强、最没有意义、最难猜到的密码从未如此简单——这都要感谢一些新功能。


理想的密码策略非常简单:强制要求最少字符数(至少 8 位)并且允许长密码(64 位或者更多)。

其他更复杂的策略,像预置的安全问题、周期性的失效密码或者强制要求一些奇怪的符号,只不过让这些策略想要保护人感到厌烦。

但是不要太相信我说的话——我不是安全专家

相对的,请查看美国国家标准技术研究所最新发布(2017 年 6 月)的 Digital Identity Guidelines

好消息是越来越多的公司和组织开始注意安全性最佳实践了。坏消息则是改变这些事情需要进行一系列影响数百万人的大范围数据改动。事实上前面说到的安全性反面模式并不会很快消失,因为公司和政府做任何事情都需要花很久的时间。

自动式强密码

Safari 的自动填充从 iOS 8 起就可以生成密码了,但是它有一个缺点就是不能保证生成的密码符合某些服务的要求。

Apple 通过 iOS 12 和 macOS Mojave 里 Safari 中的自动式强密码功能来解决这个问题。

WebKit 工程师 Daniel Bates 在 3 月 1 日给 <acronym title="Web Hypertext Application Technology Working Group" style="max-width: 100%;">WHATWG</acronym> 提交了这个提案。6 月 6 日,WebKit 团队发布了 Safari Technology Preview 58,使用新属性 passwordrules 来支持强密码生成。同时,WWDC 发布了 iOS 12 beta SDK,包括新的 UIText<wbr style="max-width: 100%;">Input<wbr style="max-width: 100%;">Password<wbr style="max-width: 100%;">Rules API,还有验证码自动输入和联合身份验证等其他一些密码管理功能。

密码规则

密码规则就像是密码生成器的配方。根据一些简单的规则,密码生成器就可以随机生成满足服务提供方需求的新密码。

密码规则由一个或多个键值对组成:

required: lower; required: upper; required: digit; allowed: ascii-printable; max-consecutive: 3;

每个规则可以指定下列键:

  • required: 需要的字符类型
  • allowed: 允许使用的字符类型
  • max-consecutive: 允许字符连续出现次数的最大值
  • minlength: 密码最小长度
  • maxlength: 密码最大长度

requiredallowed 键使用下面列出的字符类别作为值。max-consecutiveminlengthmaxlength 使用非负整数作为值。

字符类别

requiredallowed 键可以使用下面的字符类别作为值:

  • upper (A-Z)
  • lower (a-z)
  • digits (0-9)
  • special (-~!@#$%^&\*\_+=|(){}[:;"'<>,.? ]` 和空格)
  • ascii-printable (U+0020 — 007f)
  • unicode (U+0 — 10FFFF)

除了这些预置字符类别,还可以用方括号包住 ASCII 字符来指定自定义字符类别(比如 [abc])。


Apple 的 Password Rules Validation Tool 让你可以对不同的规则进行实验,并得到实时的结果反馈。甚至可以生成并下载上千个密码用来开发和测试!

image.png

更多有关于密码规则的语法,请查看 Apple 的文档「Customizing Password AutoFill Rules」


指定密码规则

在 iOS 上,给 UIText<wbr style="max-width: 100%;">Fieldpassword<wbr style="max-width: 100%;">Rules 属性设置一个 UIText<wbr style="max-width: 100%;">Input<wbr style="max-width: 100%;">Password<wbr style="max-width: 100%;">Rules 对象(同时也应该将 text<wbr style="max-width: 100%;">Content<wbr style="max-width: 100%;">Type 属性设置为 .new<wbr style="max-width: 100%;">Password):

Swift

let newPasswordTextField = UITextField()
newPasswordTextField.textContentType = .newPassword
newPasswordTextField.passwordRules = UITextInputPasswordRules(descriptor: "required: upper; required: lower; required: digit; max-consecutive: 2; minlength: 8;")

在网页上,设置 <input> 元素(且 type="password")的 passwordrules 属性:

<input type="password" passwordrules="required: upper; required: lower; required: special; max-consecutive: 3;"/>

如果没有指定,默认的密码规则是 allowed: ascii-printable。如果表单中有密码验证区域,它的密码规则会从上一个区域继承下来。

在 Swift 中生成密码规则

不光是只有你会觉得直接使用没有良好抽象的字符串格式令人感到不安。

下面是一种将密码规则封装成 Swift API 的方式(可以作为 Swift package 获取):

enum PasswordRule {
    enum CharacterClass {
        case upper, lower, digits, special, asciiPrintable, unicode
        case custom(Set<Character>)
    }

    case required(CharacterClass)
    case allowed(CharacterClass)
    case maxConsecutive(UInt)
    case minLength(UInt)
    case maxLength(UInt)
}

extension PasswordRule: CustomStringConvertible {
    var description: String {
        switch self {
        case .required(let characterClass):
            return "required: \(characterClass)"
        case .allowed(let characterClass):
            return "allowed: \(characterClass)"
        case .maxConsecutive(let length):
            return "max-consecutive: \(length)"
        case .minLength(let length):
            return "minlength: \(length)"
        case .maxLength(let length):
            return "maxlength: \(length)"
        }
    }
}

extension PasswordRule.CharacterClass: CustomStringConvertible {
    var description: String {
        switch self {
        case .upper: return "upper"
        case .lower: return "lower"
        case .digits: return "digits"
        case .special: return "special"
        case .asciiPrintable: return "ascii-printable"
        case .unicode: return "unicode"
        case .custom(let characters):
            return "[" + String(characters) + "]"
        }
    }
}

有了这个,我们就可以在代码里指定一些规则,然后用它们生成有效的密码规则语法字符串:

let rules: [PasswordRule] = [ .required(.upper),
                              .required(.lower),
                              .required(.special),
                              .minLength(20) ]

let descriptor = rules.map{ "\($0.description);" }
                      .joined(separator: " ")

// "required: upper; required: lower; required: special; max-consecutive: 3;"

只要你愿意,你甚至可以扩展 UIText<wbr style="max-width: 100%;">Input<wbr style="max-width: 100%;">Password<wbr style="max-width: 100%;">Rules 给它添加一个接收 Password<wbr style="max-width: 100%;">Rule 数组的 convenience initializer。

extension UITextInputPasswordRules {
    convenience init(rules: [PasswordRule]) {
        let descriptor = rules.map{ $0.description }
                              .joined(separator: "; ")

        self.init(descriptor: descriptor)
    }
}


如果你是一个在个人认证信息上非常有感情的人,喜欢在密码输入区域中的小圆点后面输入你的大学、小狗或者最喜欢的运动团队,请考虑不要再这样做了。

就我个人来说,我无法想象没有密码管理器的日子。当你知道任何时候你都能访问到你需要的信息,并且只有你能访问到时,你的心灵将会获得极大的平静。

从现在开始改变,你就能完全利用上在之后今年发布的 iOS 12 和 macOS Mojave 的 Safari 中的这些改进。

作者 Mattt

翻译者 Bei Li — 2018年7月23日

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容