Article|Adding a Password to the Keychain 文章|添加密码到钥匙链

1 Article|Adding a Password to the Keychain 文章|添加密码到钥匙链

Add network credentials to the keychain on behalf of the user.
为用户添加网络密码到钥匙链.

2 Overview 概述

Use keychain services to enable simple, secure storage for users’ passwords. In this way you avoid repeatedly asking the user for a password, and you don’t have to implement your own encryption, which can be error prone.
钥匙链服务可以让用户简单而安全地存储他们的密码.使用这种方式,我们不再需要频繁让用户提供密码,并且我们不用自己实现加密,自己加密往往很容易出错.

2.1 Get Set Up 开始配置

To get started, define a structure to hold the credentials as they move around your app in memory:
开始,我们定义一个结构体来保存用户名密码.

//swift:
struct Credentials {
    var username: String
    var password: String
}
//oc:
struct Credentials {
    NSString * username;
    NSString * password;
};

Next, define an error enumeration that you can use to communicate keychain access outcomes:
然后,定义一个错误枚举,你可以使用该枚举和钥匙链访问的返回值交流.

enum KeychainError: Error {
    case noPassword
    case unexpectedPasswordData
    case unhandledError(status: OSStatus)
}

Then, identify the server that your app is working with:
然后,定义应用访问的服务器:

static let server = "www.example.com"

2.2 Create an Add Query创建一个添加查询

Using an instance of the credentials structure and the server constant, you can create an add query:
使用Credentials结构体实例和server常量,创建一个添加查询:

let account = credentials.username
let password = credentials.password.data(using: String.Encoding.utf8)!
var query: [String: Any] = [kSecClass as String: kSecClassInternetPassword,
                            kSecAttrAccount as String: account,
                            kSecAttrServer as String: server,
                            kSecValueData as String: password]

The query dictionary’s first key-value pair indicates that the item is an Internet password, from which keychain services infers that the data is secret and requires encryption. This also ensures that the item has attributes that distinguish it from other Internet passwords, such as the server and account to which it applies. Indeed, the next two key-value pairs in the query provide this information, attaching the user name acquired from the user as the account, along with a domain name appropriate to this password as the server.
查询字典的第一个键值对标识这个钥匙链项目的类型是一个网络密码,钥匙链服务根据该类型推断该数据是私密的,并且需要加密.并且确保该项目包含区别其他网络密码的属性,比如该密码要应用的服务器和账号.接下来的两个键值对的确也提供了这些信息,用户名作为账号,密码使用的域名作为服务器.

Note注意:
Keychain services also offers the related kSecClassGenericPassword item class. Generic passwords are similar in most respects to Internet passwords, but they lack certain attributes specific to remote access (for example, they don’t have a kSecAttrServer attribute). When you don’t need these extra attributes, use a generic password instead.
钥匙链服务还提供了kSecClassGenericPassword类型的钥匙链项目.通用密码和网络密码在很多方面相同,但是通用密码缺少特定表明远程访问的属性(比如,他们没有kSecAttrServer属性).如果你不需要这些属性,使用通用密码替代.

Although not necessary in this case, you could further characterize the password by specifying additional attributes, such as the port number or the network protocol. For example, if you needed to store distinct FTP and HTTP credentials for the same user working on the same server, you could add the kSecAttrProtocol attribute to distinguish between them.
尽管在该示例中不需要,但是你可以更进一步地描述这个密码,通过指定附加的属性,比如端口号或者网络协议.比如,如果你需要分别存储同一个用户在同一个服务器上的FTP密码和HTTP密码,你需要增加kSecAttrProtocol属性来区分他们.

Finally, the query contains the password from the user, encoded as a Data instance.
最后,该查询包含了用户的密码,该密码被编码为NSData类型.

2.3 Add the Item添加钥匙链项目

With the query complete, you simply feed it to the SecItemAdd function:
查询已经创建完毕,现在只需要将它传入SecItemAdd函数:

let status = SecItemAdd(query as CFDictionary, nil)
guard status == errSecSuccess else { throw KeychainError.unhandledError(status: status) }

Although you typically ignore the return data supplied by reference in the second argument on an add operation (as demonstrated here), always check the function’s return status to ensure that the operation succeeds. The operation might fail, for example, if an item with the given attributes already exists.
尽管通常在添加操作中忽略第二个参数引用的返回数据,我们还是应该要检查函数的返回状态来确保操作成功.该操作可能失败,例如,一个具有相同属性的项目已经存在.

Note注意:
If you do want the return data, keep in mind that the SecItemAdd function behaves much like the SecItemCopyMatching function in this regard. See Searching for Keychain Items for details.
如果你需要返回的数据,需要留心SecItemAdd函数在这一点上和SecItemCopyMatching函数是很类似的.要了解详细信息,请参考Searching for Keychain Items查询钥匙链项目

2.4 Ensure Searchability确保可查询性

To be able to find the item later, you’re going to use your knowledge of its attributes. In this example, the server and the account are the item’s distinguishing characteristics. For constant attributes (here, the server), use the same value during lookup. In contrast, the account attribute is dynamic, because it holds a value provided by the user at runtime. As long as your app never adds similar items with varying attributes (such as passwords for different accounts on the same server), you can omit these dynamic attributes as search parameters and instead retrieve them along with the item. As a result, when you look up the password, you also get the corresponding username.
为了能够在之后找到该项目,你必须使用项目的属性.在这个例子中,服务器和账号是该项目用以区别其他项目的特征.对于常量属性(在这里是服务器属性),在查询时,使用一样的值.相反,账号属性是动态的,因为他是用户在运行时提供的.只要你的应用不填加不同属性的类似的项目(比如同一个服务器上不同账号的密码),你可以省略这些动态属性,并且将这些属性和钥匙链项目一起得到.这就导致了,当你查询密码时,你同时得到了对应的用户名.

If your app does add items with varying dynamic attributes, you’ll need a way to choose among them during retrieval. One option is to record information about the items in another way. For example, if you keep records of users in a Core Data model, you store the username there after using keychain services to store the password field. Later, you use the user name pulled from your data model to condition the search for the password.
如果你的应用添加了不同的动态属性的项目,你需要一种方式在检索中选择你需要的.一个选择是用另一种方式记录项目的信息.比如,如果你使用CoreData中保存用户记录,那么,你在使用钥匙链服务保存密码后,同事保存用户名.之后,你使用数据模型中得到的用户名来寻找密码.

In other cases, it may make sense to further characterize the item by adding more attributes. For example, you might include the kSecAttrLabel attribute in the original add query, providing a string that marks the item for the particular purpose. Then you’ll be able to use this attribute to narrow your search later.
在其他情况下,添加更多的属性进一步描述钥匙链项目是很有意义的.比如,你可以在原始添加查询中添加kSecAttrLabel属性,该属性提供了一个字符串来标记该项目的特定作用.之后,你可以通过该属性来缩小你的查询.

3 See Also参考

3.1 Adding Keychain Items添加钥匙链项目

3.1.1 SecItemAdd

Adds one or more items to a keychain.
保存一个或者多个钥匙链项目到钥匙链.

3.1.3 Item Class Keys and Values 钥匙链项目的类型的键与值

Specify the class of a keychain item.
指定钥匙链项目的类型.

3.1.3 Item Attribute Keys and Values 钥匙链项目的属性的键与值

Specify the attributes of keychain items.
指定钥匙链项目的属性.

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

推荐阅读更多精彩内容