為用戶添加網絡密碼到鑰匙鏈.
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.
鑰匙鏈服務可以讓用戶簡單而安全地存儲他們的密碼.使用這種方式,我們不再需要頻繁讓用戶提供密碼,並且我們不用自己實現加密,自己加密往往很容易出錯.
To get started, define a structure to hold the credentials as they move around your app in memory:
開始,我們定義壹個結構體來保存用戶名密碼.
Next, define an error enumeration that you can use to communicate keychain access outcomes:
然後,定義壹個錯誤枚舉,妳可以使用該枚舉和鑰匙鏈訪問的返回值交流.
Then, identify the server that your app is working with:
然後,定義應用訪問的服務器:
Using an instance of the credentials structure and the server constant, you can create an add query:
使用Credentials結構體實例和server常量,創建壹個添加查詢:
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類型.
With the query complete, you simply feed it to the SecItemAdd function:
查詢已經創建完畢,現在只需要將它傳入SecItemAdd函數:
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查詢鑰匙鏈項目
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屬性,該屬性提供了壹個字符串來標記該項目的特定作用.之後,妳可以通過該屬性來縮小妳的查詢.
Adds one or more items to a keychain.
保存壹個或者多個鑰匙鏈項目到鑰匙鏈.
Specify the class of a keychain item.
指定鑰匙鏈項目的類型.
Specify the attributes of keychain items.
指定鑰匙鏈項目的屬性.