zoukankan      html  css  js  c++  java
  • SFHFKeychainUtils 存储用户信息

    SFHFKeychainUtils密码保护,使用方法很简单

    下载地址

    https://github.com/ldandersen/scifihifi-iphone/tree/master/security

    1、引入Security.frameWork框架。

    2、引入头文件:SFHKeychainUtils.h.

    3、存密码:

    [SFHFKeychainUtils storeUsername:@"dd" andPassword:@"aa"forServiceName:SERVICE_NAME updateExisting:1 error:nil];

    [SFHFKeychainUtils deleteItemForUsername:@"dd" andServiceName:SERVICE_NAME error:nil];

    4、取密码:

    NSString *passWord =  [SFHFKeychainUtils getPasswordForUsername:@"dd"andServiceName:SERVICE_NAME error:nil];

     

    SFHFKeychainUtils.h 文件

    #import <UIKit/UIKit.h>

    @interface SFHFKeychainUtils : NSObject {

      

    }

     + (NSString *) getPasswordForUsername: (NSString *) username 

      andServiceName: (NSString *) serviceName 

    error: (NSError **) error;

     

    + (BOOL) storeUsername: (NSString *) username 

      andPassword: (NSString *) password 

    forServiceName: (NSString *) serviceName 

    updateExisting: (BOOL) updateExisting 

    error: (NSError **) error;

     

    + (BOOL) deleteItemForUsername: (NSString *) username 

    andServiceName: (NSString *) serviceName 

    error: (NSError **) error;

    @end

    SFHFKeychainUtils.m文件

    #import "SFHFKeychainUtils.h"

    #import <Security/Security.h>

     

    static NSString *SFHFKeychainUtilsErrorDomain = @"SFHFKeychainUtilsErrorDomain";

     

    #if __IPHONE_OS_VERSION_MIN_REQUIRED < 30000 && TARGET_IPHONE_SIMULATOR

    @interface SFHFKeychainUtils (PrivateMethods)

    + (SecKeychainItemRef) getKeychainItemReferenceForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error;

    @end

    #endif

     

    @implementation SFHFKeychainUtils

     

    #if __IPHONE_OS_VERSION_MIN_REQUIRED < 30000 && TARGET_IPHONE_SIMULATOR

     

    + (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error {

    if (!username || !serviceName) {

    *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];

    returnnil;

    }

     

    SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error];

     

    if (*error || !item) {

    returnnil;

    }

     

    // from Advanced Mac OS X Programming, ch. 16

      UInt32 length;

      char *password;

      SecKeychainAttribute attributes[8];

      SecKeychainAttributeList list;

     

      attributes[0].tag = kSecAccountItemAttr;

      attributes[1].tag = kSecDescriptionItemAttr;

      attributes[2].tag = kSecLabelItemAttr;

      attributes[3].tag = kSecModDateItemAttr;

      

      list.count = 4;

      list.attr = attributes;

      

      OSStatus status = SecKeychainItemCopyContent(item, NULL, &list, &length, (void **)&password);

     

    if (status != noErr) {

    *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];

    returnnil;

      }

      

    NSString *passwordString = nil;

     

    if (password != NULL) {

    char passwordBuffer[1024];

     

    if (length > 1023) {

    length = 1023;

    }

    strncpy(passwordBuffer, password, length);

     

    passwordBuffer[length] = '\0';

    passwordString = [NSString stringWithCString:passwordBuffer];

    }

     

    SecKeychainItemFreeContent(&list, password);

      

      CFRelease(item);

      

      return passwordString;

    }

     

    + (void) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error {

    if (!username || !password || !serviceName) {

    *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];

    return;

    }

     

    OSStatus status = noErr;

     

    SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error];

     

    if (*error && [*error code] != noErr) {

    return;

    }

     

    *error = nil;

     

    if (item) {

    status = SecKeychainItemModifyAttributesAndData(item,

                                                        NULL,

                                                        strlen([password UTF8String]),

                                                        [password UTF8String]);

     

    CFRelease(item);

    }

    else {

    status = SecKeychainAddGenericPassword(NULL,                                     

                                               strlen([serviceName UTF8String]), 

                                               [serviceName UTF8String],

                                               strlen([username UTF8String]),                        

                                               [username UTF8String],

                                               strlen([password UTF8String]),

                                               [password UTF8String],

                                               NULL);

    }

     

    if (status != noErr) {

    *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];

    }

    }

     

    + (void) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error {

    if (!username || !serviceName) {

    *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: 2000 userInfo: nil];

    return;

    }

     

    *error = nil;

     

    SecKeychainItemRef item = [SFHFKeychainUtils getKeychainItemReferenceForUsername: username andServiceName: serviceName error: error];

     

    if (*error && [*error code] != noErr) {

    return;

    }

     

    OSStatus status;

     

    if (item) {

    status = SecKeychainItemDelete(item);

     

    CFRelease(item);

    }

     

    if (status != noErr) {

    *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];

    }

    }

     

    + (SecKeychainItemRef) getKeychainItemReferenceForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error {

    if (!username || !serviceName) {

    *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: -2000 userInfo: nil];

    returnnil;

    }

     

    *error = nil;

      

    SecKeychainItemRef item;

     

    OSStatus status = SecKeychainFindGenericPassword(NULL,

                                                       strlen([serviceName UTF8String]),

                                                       [serviceName UTF8String],

                                                       strlen([username UTF8String]),

                                                       [username UTF8String],

                                                       NULL,

                                                       NULL,

                                                       &item);

     

    if (status != noErr) {

    if (status != errSecItemNotFound) {

    *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];

    }

     

    returnnil;

    }

     

    return item;

    }

     

    #else

     

    + (NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error {

    if (!username || !serviceName) {

    if (error != nil) {

    *error = [NSErrorerrorWithDomain: SFHFKeychainUtilsErrorDomaincode: -2000userInfo: nil];

    }

    returnnil;

    }

     

    if (error != nil) {

    *error = nil;

    }

      

    // Set up a query dictionary with the base query attributes: item type (generic), username, and service

     

    NSArray *keys = [[[NSArrayalloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, kSecAttrService, nil] autorelease];

    NSArray *objects = [[[NSArray alloc] initWithObjects: (NSString *) kSecClassGenericPassword, username, serviceName, nil] autorelease];

     

    NSMutableDictionary *query = [[[NSMutableDictionaryalloc] initWithObjects: objects forKeys: keys] autorelease];

     

    // First do a query for attributes, in case we already have a Keychain item with no password data set.

    // One likely way such an incorrect item could have come about is due to the previous (incorrect)

    // version of this code (which set the password as a generic attribute instead of password data).

     

    NSDictionary *attributeResult = NULL;

    NSMutableDictionary *attributeQuery = [query mutableCopy];

    [attributeQuery setObject: (id) kCFBooleanTrueforKey:(id) kSecReturnAttributes];

    OSStatus status = SecItemCopyMatching((CFDictionaryRef) attributeQuery, (CFTypeRef *) &attributeResult);

     

    [attributeResult release];

    [attributeQuery release];

     

    if (status != noErr) {

    // No existing item found--simply return nil for the password

    if (error != nil && status != errSecItemNotFound) {

    //Only return an error if a real exception happened--not simply for "not found."

    *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];

    }

     

    returnnil;

    }

     

    // We have an existing item, now query for the password data associated with it.

     

    NSData *resultData = nil;

    NSMutableDictionary *passwordQuery = [query mutableCopy];

    [passwordQuery setObject: (id) kCFBooleanTrue forKey: (id) kSecReturnData];

      

    status = SecItemCopyMatching((CFDictionaryRef) passwordQuery, (CFTypeRef *) &resultData);

     

    [resultData autorelease];

    [passwordQuery release];

     

    if (status != noErr) {

    if (status == errSecItemNotFound) {

    // We found attributes for the item previously, but no password now, so return a special error.

    // Users of this API will probably want to detect this error and prompt the user to

    // re-enter their credentials.  When you attempt to store the re-entered credentials

    // using storeUsername:andPassword:forServiceName:updateExisting:error

    // the old, incorrect entry will be deleted and a new one with a properly encrypted

    // password will be added.

    if (error != nil) {

    *error = [NSErrorerrorWithDomain: SFHFKeychainUtilsErrorDomaincode: -1999userInfo: nil];

    }

    }

    else {

    // Something else went wrong. Simply return the normal Keychain API error code.

    if (error != nil) {

    *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];

    }

    }

     

    returnnil;

    }

      

    NSString *password = nil;

      

    if (resultData) {

    password = [[NSStringalloc] initWithData: resultData encoding: NSUTF8StringEncoding];

    }

    else {

    // There is an existing item, but we weren't able to get password data for it for some reason,

    // Possibly as a result of an item being incorrectly entered by the previous code.

    // Set the -1999 error so the code above us can prompt the user again.

    if (error != nil) {

    *error = [NSErrorerrorWithDomain: SFHFKeychainUtilsErrorDomaincode: -1999userInfo: nil];

    }

    }

      

    return [password autorelease];

    }

     

    + (BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error 

    {

    if (!username || !password || !serviceName) 

      {

    if (error != nil

        {

    *error = [NSErrorerrorWithDomain: SFHFKeychainUtilsErrorDomaincode: -2000userInfo: nil];

    }

    returnNO;

    }

     

    // See if we already have a password entered for these credentials.

    NSError *getError = nil;

    NSString *existingPassword = [SFHFKeychainUtils getPasswordForUsername: username andServiceName: serviceName error:&getError];

      

    if ([getError code] == -1999

      {

    // There is an existing entry without a password properly stored (possibly as a result of the previous incorrect version of this code.

    // Delete the existing item before moving on entering a correct one.

        

    getError = nil;

     

    [self deleteItemForUsername: username andServiceName: serviceName error: &getError];

        

    if ([getError code] != noErr

        {

    if (error != nil

          {

    *error = getError;

    }

    returnNO;

    }

    }

    else if ([getError code] != noErr

      {

    if (error != nil

        {

    *error = getError;

    }

    returnNO;

    }

     

    if (error != nil

      {

    *error = nil;

    }

     

    OSStatus status = noErr;

      

    if (existingPassword) 

      {

    // We have an existing, properly entered item with a password.

    // Update the existing item.

     

    if (![existingPassword isEqualToString:password] && updateExisting) 

        {

    //Only update if we're allowed to update existing.  If not, simply do nothing.

     

    NSArray *keys = [[[NSArrayalloc] initWithObjects: (NSString *) kSecClass

                            kSecAttrService

                            kSecAttrLabel

                            kSecAttrAccount

                            nil] autorelease];

     

    NSArray *objects = [[[NSArrayalloc] initWithObjects: (NSString *) kSecClassGenericPassword

                               serviceName,

                               serviceName,

                               username,

                               nil] autorelease];

     

    NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];

     

    status = SecItemUpdate((CFDictionaryRef) query, (CFDictionaryRef) [NSDictionarydictionaryWithObject: [password dataUsingEncoding: NSUTF8StringEncoding] forKey: (NSString *) kSecValueData]);

    }

    }

    else 

      {

    // No existing entry (or an existing, improperly entered, and therefore now

    // deleted, entry).  Create a new entry.

     

    NSArray *keys = [[[NSArrayalloc] initWithObjects: (NSString *) kSecClass

                          kSecAttrService

                          kSecAttrLabel

                          kSecAttrAccount

                          kSecValueData

                          nil] autorelease];

     

    NSArray *objects = [[[NSArrayalloc] initWithObjects: (NSString *) kSecClassGenericPassword

                             serviceName,

                             serviceName,

                             username,

                             [password dataUsingEncoding: NSUTF8StringEncoding],

                             nil] autorelease];

     

    NSDictionary *query = [[[NSDictionary alloc] initWithObjects: objects forKeys: keys] autorelease];

        

    status = SecItemAdd((CFDictionaryRef) query, NULL);

    }

     

    if (error != nil && status != noErr

      {

    // Something went wrong with adding the new item. Return the Keychain error code.

    *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];

        

        returnNO;

    }

      

      returnYES;

    }

     

    + (BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error 

    {

    if (!username || !serviceName) 

      {

    if (error != nil

        {

    *error = [NSErrorerrorWithDomain: SFHFKeychainUtilsErrorDomaincode: -2000userInfo: nil];

    }

    returnNO;

    }

     

    if (error != nil

      {

    *error = nil;

    }

      

    NSArray *keys = [[[NSArrayalloc] initWithObjects: (NSString *) kSecClass, kSecAttrAccount, kSecAttrService, kSecReturnAttributes, nil] autorelease];

    NSArray *objects = [[[NSArrayalloc] initWithObjects: (NSString *) kSecClassGenericPassword, username, serviceName, kCFBooleanTrue, nil] autorelease];

     

    NSDictionary *query = [[[NSDictionaryalloc] initWithObjects: objects forKeys: keys] autorelease];

     

    OSStatus status = SecItemDelete((CFDictionaryRef) query);

     

    if (error != nil && status != noErr

      {

    *error = [NSError errorWithDomain: SFHFKeychainUtilsErrorDomain code: status userInfo: nil];

        

        returnNO;

    }

      

      returnYES;

    }

     

    #endif

     

    @end

  • 相关阅读:
    干净卸载mysql (注册表)
    计算机中丢失 MSVCR100.dll
    ORM框架SQLAlchemy学习笔记
    mac sourcetree required password
    ConstantBuffer
    Unity通用渲染管线Shader日志输出工具
    Unity SRP Batcher的工作原理
    Unity中的深度测试相关知识与问题
    渲染杂谈:early-z、z-culling、hi-z、z-perpass到底是什么?
    Unity Compute Shader入门初探
  • 原文地址:https://www.cnblogs.com/jiangshiyong/p/2720694.html
Copyright © 2011-2022 走看看