在 iOS 中将电子邮件/密码保存到钥匙串

2024-04-07

我对 iOS 开发非常陌生,所以如果这是一个新手问题,请原谅我。我的应用程序有一个简单的身份验证机制,它需要用户的电子邮件地址和密码。我还有一个开关,上面写着“记住我”。如果用户打开该开关,我想保留他们的电子邮件/密码,以便将来可以自动填充这些字段。

我已经将其与保存到 plist 文件一起使用,但我知道这不是最好的主意,因为密码未加密。我找到了一些保存到钥匙串的示例代码,但说实话,我有点迷失。对于下面的函数,我不确定如何调用它以及如何修改它以保存电子邮件地址。

我猜调用它会是:saveString(@"passwordgoeshere");

感谢您的任何帮助!!!

+ (void)saveString:(NSString *)inputString forKey:(NSString *)account {

    NSAssert(account != nil, @"Invalid account");
    NSAssert(inputString != nil, @"Invalid string");

    NSMutableDictionary *query = [NSMutableDictionary dictionary];

    [query setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
    [query setObject:account forKey:(id)kSecAttrAccount];
    [query setObject:(id)kSecAttrAccessibleWhenUnlocked forKey:(id)kSecAttrAccessible];

    OSStatus error = SecItemCopyMatching((CFDictionaryRef)query, NULL);
    if (error == errSecSuccess) {
        // do update
        NSDictionary *attributesToUpdate = [NSDictionary dictionaryWithObject:[inputString dataUsingEncoding:NSUTF8StringEncoding] 
                                                                      forKey:(id)kSecValueData];

        error = SecItemUpdate((CFDictionaryRef)query, (CFDictionaryRef)attributesToUpdate);
        NSAssert1(error == errSecSuccess, @"SecItemUpdate failed: %d", error);
    } else if (error == errSecItemNotFound) {
        // do add
        [query setObject:[inputString dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData];

        error = SecItemAdd((CFDictionaryRef)query, NULL);
        NSAssert1(error == errSecSuccess, @"SecItemAdd failed: %d", error);
    } else {
        NSAssert1(NO, @"SecItemCopyMatching failed: %d", error);
    }
}

我编写了一个简单的包装器,允许将任何符合 NSCoding 的对象保存到钥匙串中。例如,您可以将电子邮件和密码存储在 NSDictionary 中,并使用此类将 NSDictionary 存储到钥匙串中。

简单钥匙串.h

#import <Foundation/Foundation.h>

@class SimpleKeychainUserPass;

@interface SimpleKeychain : NSObject

+ (void)save:(NSString *)service data:(id)data;
+ (id)load:(NSString *)service;
+ (void)delete:(NSString *)service;

@end

简单钥匙串.m

#import "SimpleKeychain.h"

@implementation SimpleKeychain

+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:
            (id)kSecClassGenericPassword, (id)kSecClass,
            service, (id)kSecAttrService,
            service, (id)kSecAttrAccount,
            (id)kSecAttrAccessibleAfterFirstUnlock, (id)kSecAttrAccessible,
            nil];
}

+ (void)save:(NSString *)service data:(id)data {
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    SecItemDelete((CFDictionaryRef)keychainQuery);
    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
    SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
}

+ (id)load:(NSString *)service {
    id ret = nil;
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
    [keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
    CFDataRef keyData = NULL;
    if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
        @try {
            ret = [NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)keyData];
        }
        @catch (NSException *e) {
            NSLog(@"Unarchive of %@ failed: %@", service, e);
        }
        @finally {}
    }
    if (keyData) CFRelease(keyData);
    return ret;
}

+ (void)delete:(NSString *)service {
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
    SecItemDelete((CFDictionaryRef)keychainQuery);
}

@end
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 iOS 中将电子邮件/密码保存到钥匙串 的相关文章

随机推荐

  • 芹菜“重试”并更新参数

    考虑一个任务将列表作为参数并处理列表中的每个元素 这可能会成功也可能会失败 在这种情况下 如何仅对失败的元素进行 重试 Example app task bind True def my test self my list list new
  • 在 bash 脚本中模拟用户输入[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我正在创建自己的 bash 脚本 但目前陷入困境 基本上 该脚本将用于在 CentOS 中自动设置服务器 某些软件通常要求用户输入密码 我希望脚本将我
  • 将复选框添加到 ASP.NET 网格视图

    我正在尝试在我的网络应用程序中启用批量删除 我显示的数据位于GridView我想添加一列 其中每一行包含一个复选框 或任何替代选项 用户可以标记要删除的行 然后立即删除所有行 当我添加一个CheckBoxField 它必须绑定到我自然在数据
  • 删除元素时映射迭代器如何失效? [复制]

    这个问题在这里已经有答案了 使用擦除方法时 迭代器何时以及如何在映射中失效 例如 std map lt int int gt aMap aMap 33 1 aMap 42 10000 aMap 69 100 aMap 666 1 std m
  • WordPress 到 Jekyll 脚本抛出错误

    我已经为这个问题苦苦挣扎了一天左右 但无法弄清楚发生了什么 我正在尝试运行一个脚本将我的 Wordpress sql 导入 Jekyll 并将所有内容转换为 Markdown 但每次我运行脚本 在 Mac 和 Ubuntu 上 时都会收到错
  • Python定时器回调方法

    from threading import Timer class test timer def init self self awesum hh self timer Timer 1 self say hello args WOW def
  • 在 Grails 中使用 Groovy++ 的经验

    有人尝试过在幕后实现一个包含 Groovy 的 Grails 解决方案吗 Groovy 使用 Groovy 1 7 5 并包含将 G 与 Grails 集成的插件
  • 当键盘在 Flutter TextField 中可见时,键盘顶部有大量空白

    这是我的代码 build BuildContext context return new Scaffold body new SafeArea child new ListView builder itemBuilder itemBuild
  • 动态更改从数组创建的按钮的按钮标签和标题(快速)

    我的环境 下面的代码是在我公司 iPad 上的 swift Playgrounds 4 中编写的 项目目标 我正在努力改进学校的课堂管理工具 它基本上是一个纸质交通灯 每个学生都有一个衣夹 我想要一个应用程序 其中我的 28 个学生都由一个
  • pthread_mutex_t 可以在内存中移动吗?

    我想构建一个动态分配的 pthread mutex 数组 该数组将随着时间的推移而增长 添加更多互斥体 我的问题是 如果数组通过 realloc 移动 它们是否仍然有效 我担心的是 pthread mutex init 可能会以某种方式设置
  • 更新具有一个字段的当前最高(最大值)值的行[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我有这个 SQL 查询 这是错误的
  • 在Java中,如何从资源构造文件?

    File 在其构造函数中采用 String 和 URI getClass getResource 返回 URL 和getResourceAsStream 返回输入流 有没有办法从资源构造文件 你不能 至少在资源位于 Jar 内的标准情况下不
  • JPA/Hibernate - 与子实体一起分离实体

    我使用 JPA 2 和 Hibernate 3 6 8 作为实现 假设我们有一个实体Foo Entity public class Foo OneToOne private Bar bar 我需要将整个实体图从会话中分离出来 当我这样做时e
  • 使用 Java 将数据从 Cassandra 中的一个表复制到另一个表

    我正在尝试将所有数据从一个列族 表 移动到另一个列族 由于两个表都有不同的描述 我必须从 table 1 中提取所有数据并为 table 2 创建一个新对象 然后执行批量 aync 插入 我的 table 1 有数百万条记录 因此我无法直接
  • 如何使用Lua脚本语言打开Web套接字?

    作为初学者 我想在基于 Linux 的服务器上使用 Lua 打开一个 Web 套接字 该服务器应允许 Android 客户端连接到它 你能给我一些用Lua打开网络套接字的示例代码吗 您两周前已经问过同样的问题并得到了回答 LUA 脚本 We
  • 在 html5 Canvas 上移动对象

    我使用 fillText 选项在 html5 canvas 对象上放置了一个文本 问题是我需要移动文本位置或更改已渲染文本的颜色 很快我需要知道如何操作画布元素的特定子元素 这将在画布上移动一个小圆圈 var can document ge
  • 为什么 ng-bind-html 不显示任何内容?

    我正在显示一个包含 HTML 代码的字符串 div style font size 14px div put 它显示 HTML 代码而不是解释元素 当我使用ng bind and ng bind unsafe 它什么也没显示 如何获取要解析
  • 使用 df.merge 填充 df 中的新列给出奇怪的匹配

    我刚刚发现导致此问题的 2 个问题 请参阅下面的解决方案 我想基于另一个数据帧在我的数据帧 df 中创建一个新列 基本上 df2 包含我想要插入 df 的更新信息 为了复制我的真实情况 gt 1m 行 我将用简单的列填充两个随机 df 我使
  • 如何使用app.config.from_envvar? (烧瓶)

    如何使用app config from envvar 我查看了 Flask 文档并搜索了这个主题 我所知道的就是这样做 DATABASE flaskr db DEBUG True SECRET KEY development key app
  • 在 iOS 中将电子邮件/密码保存到钥匙串

    我对 iOS 开发非常陌生 所以如果这是一个新手问题 请原谅我 我的应用程序有一个简单的身份验证机制 它需要用户的电子邮件地址和密码 我还有一个开关 上面写着 记住我 如果用户打开该开关 我想保留他们的电子邮件 密码 以便将来可以自动填充这