0Pricing
Swift Academy · บทเรียน

การจัดเก็บข้อมูลลับใน Keychain

บันทึกและเรียกข้อมูลข้อมูลประจำตัวอย่างปลอดภัย

การจัดเก็บข้อมูลลับใน Keychain เป็นบทเรียน Swift Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Swift Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน

เหตุผลที่ใช้พวงกุญแจ

รหัสผ่าน โทเค็น และคีย์ต้องไม่เก็บไว้ใน UserDefaults หรือไฟล์ธรรมดา เพราะอ่านได้ง่าย พวงกุญแจคือฐานข้อมูลลับขนาดเล็กที่เข้ารหัสและจัดการโดย OS ปกป้องด้วยฮาร์ดแวร์และรหัสผ่านของผู้ใช้ นี่เป็นสถานที่ที่ถูกต้องเพียงแห่งเดียวสำหรับข้อมูลรับรอง

import Security
// Keychain stores secrets encrypted at rest,
// survives app updates, and gates access by policy.

รายการคือพจนานุกรม

API ของบริการพวงกุญแจใช้ภาษา C: คุณอธิบายรายการด้วยพจนานุกรมคำขอ [String: Any] โดยใช้คีย์ค่าคงที่ kSec... รูปแบบพจนานุกรมเดียวกันนี้ใช้ซ้ำสำหรับการเพิ่ม การค้นหา การอัปเดต และการลบ

import Security
let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrAccount as String: "user@example.com",
    kSecAttrService as String: "com.example.app"
]
_ = query

ประเภทของรายการ

คีย์ kSecClass ใช้เลือกประเภทของรายการ kSecClassGenericPassword ครอบคลุมโทเค็นและข้อมูลลับของแอป ส่วน kSecClassInternetPassword ใช้เก็บข้อมูลรับรองของเซิร์ฟเวอร์พร้อมแอตทริบิวต์ของโฮสต์และโพรโทคอล ข้อมูลลับของแอปส่วนใหญ่ใช้รหัสผ่านทั่วไป

import Security
// kSecClassGenericPassword   -> tokens, API keys
// kSecClassInternetPassword  -> server logins
// kSecClassKey / Certificate -> crypto material
let cls = kSecClassGenericPassword
_ = cls

การเพิ่มรายการ

SecItemAdd จะแทรกรายการใหม่ คุณต้องใส่ข้อมูลภายใต้ kSecValueData ในรูปแบบ Data พร้อมแอตทริบิวต์ที่ใช้ระบุรายการ เมธอดนี้ส่งคืนค่า OSStatus โดย errSecSuccess หมายถึงดำเนินการสำเร็จ

import Security
func save(_ token: String, account: String) -> Bool {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: account,
        kSecValueData as String: Data(token.utf8)
    ]
    return SecItemAdd(query as CFDictionary, nil)
        == errSecSuccess
}

การจัดการรายการซ้ำ

การเพิ่มรายการที่มีแอตทริบิวต์สำหรับระบุรายการซ้ำกับของเดิม จะส่งคืนค่า errSecDuplicateItem การบันทึกที่รับมือได้ดีจะลองใช้ SecItemAdd และหากพบรายการซ้ำ จะใช้ SecItemUpdate เป็นทางเลือก ซึ่งเป็นรูปแบบ upsert

import Security
func upsert(_ data: Data, account: String) -> Bool {
    let base: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: account]
    var add = base
    add[kSecValueData as String] = data
    let status = SecItemAdd(add as CFDictionary, nil)
    if status == errSecDuplicateItem {
        return SecItemUpdate(base as CFDictionary,
            [kSecValueData as String: data] as CFDictionary)
            == errSecSuccess
    }
    return status == errSecSuccess
}

การอ่านรายการกลับมา

SecItemCopyMatching ใช้ค้นหา หากต้องการรับไบต์ของข้อมูลลับ คุณต้องตั้งค่า kSecReturnData เป็น true และตั้งค่า kSecMatchLimit เป็น kSecMatchLimitOne ผลลัพธ์จะถูกส่งกลับผ่านพารามิเตอร์ผลลัพธ์เป็น CFTypeRef

import Security
func load(account: String) -> Data? {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: account,
        kSecReturnData as String: true,
        kSecMatchLimit as String: kSecMatchLimitOne]
    var result: CFTypeRef?
    let status = SecItemCopyMatching(
        query as CFDictionary, &result)
    guard status == errSecSuccess else { return nil }
    return result as? Data
}

การอัปเดตรายการ

SecItemUpdate รับพจนานุกรมสองชุด ได้แก่ คิวรีที่ใช้ค้นหารายการ และพจนานุกรมแอตทริบิวต์ที่ต้องการอัปเดต เฉพาะแอตทริบิวต์ที่คุณระบุเท่านั้นที่จะเปลี่ยนแปลง ส่วนอื่นจะคงเดิม

import Security
func update(_ newData: Data, account: String) -> Bool {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: account]
    let attrs: [String: Any] = [
        kSecValueData as String: newData]
    return SecItemUpdate(query as CFDictionary,
        attrs as CFDictionary) == errSecSuccess
}

การลบรายการ

SecItemDelete ลบรายการที่ตรงกัน หากลบสิ่งที่ไม่มีอยู่ ระบบจะส่งคืน errSecItemNotFound ซึ่งคุณสามารถถือว่าเป็นความสำเร็จได้เมื่อกำลังล้างข้อมูลรับรองระหว่างออกจากระบบ

import Security
func delete(account: String) -> Bool {
    let query: [String: Any] = [
        kSecClass as String: kSecClassGenericPassword,
        kSecAttrAccount as String: account]
    let status = SecItemDelete(query as CFDictionary)
    return status == errSecSuccess
        || status == errSecItemNotFound
}

การถอดรหัส OSStatus

ข้อผิดพลาดจะแสดงเป็นรหัสจำนวนเต็มของ OSStatus ส่วน SecCopyErrorMessageString จะแปลงรหัสหนึ่งรายการให้เป็นคำอธิบายที่มนุษย์อ่านเข้าใจได้ ซึ่งมีประโยชน์อย่างยิ่งเมื่อตรวจแก้ปัญหาว่าเหตุใดการบันทึกหรือการอ่านจึงล้มเหลว

import Security
func describe(_ status: OSStatus) -> String {
    return SecCopyErrorMessageString(status, nil)
        as String? ?? "OSStatus \(status)"
}

การระบุรายการให้ไม่ซ้ำกัน

ระบบจับคู่รายการจากการรวมกันของแอตทริบิวต์ โดยทั่วไปคือ kSecAttrService ร่วมกับ kSecAttrAccount สำหรับรหัสผ่านทั่วไป โปรดเลือกสตริง service ที่คงที่และเฉพาะสำหรับแอป เพื่อไม่ให้ข้อมูลลับต่างกันชนกัน

import Security
// Uniqueness for generic passwords usually comes from:
//   service (your bundle id) + account (the username)
let service = "com.example.app.auth"
let account = "current-user"
_ = (service, account)

ตัวห่อหุ้มขนาดเล็ก

เนื่องจาก API แบบดิบมีรายละเอียดมาก ทีมต่าง ๆ จึงมักห่อหุ้มไว้ในชนิดข้อมูลขนาดเล็กที่เปิดให้ใช้ save, read และ delete วิธีนี้ทำให้ขั้นตอนของ kSec อยู่รวมกันในที่เดียว และจุดเรียกใช้งานดูสะอาดตา

import Security
struct TokenStore {
    let service = "com.example.app.auth"
    func read(_ account: String) -> Data? {
        let q: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrService as String: service,
            kSecAttrAccount as String: account,
            kSecReturnData as String: true,
            kSecMatchLimit as String: kSecMatchLimitOne]
        var out: CFTypeRef?
        return SecItemCopyMatching(q as CFDictionary, &out)
            == errSecSuccess ? out as? Data : nil
    }
}

ตรวจสอบความเข้าใจ

ทบทวนวิธีที่ถูกต้องในการดึงไบต์ของข้อมูลลับที่จัดเก็บไว้

สรุปทบทวน

คุณได้เรียนรู้การสร้าง อ่าน แก้ไข และลบข้อมูลในพวงกุญแจ:

  • เก็บข้อมูลรับรองไว้ในพวงกุญแจที่เข้ารหัส อย่าเก็บไว้ใน UserDefaults หรือไฟล์
  • อธิบายรายการด้วยพจนานุกรมคิวรีของ kSec และเลือกคลาส เช่น kSecClassGenericPassword
  • SecItemAdd / SecItemCopyMatching / SecItemUpdate / SecItemDelete ครอบคลุมวงจรการใช้งาน ให้จัดการ errSecDuplicateItem ด้วยการเพิ่มรายการใหม่หรืออัปเดตรายการเดิม
  • ระบุรายการด้วย service + account และถอดรหัส OSStatus เพื่อช่วยตรวจแก้ปัญหา

คำถามที่พบบ่อย

บทเรียน “การจัดเก็บข้อมูลลับใน Keychain” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การจัดเก็บข้อมูลลับใน Keychain” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Swift Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Swift Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การจัดเก็บข้อมูลลับใน Keychain”

บันทึกและเรียกข้อมูลข้อมูลประจำตัวอย่างปลอดภัย คุณปฏิบัติ Swift Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Swift Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Swift Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “การจัดเก็บข้อมูลลับใน Keychain” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Swift Academy นี้ได้ไหม

ได้ บทเรียน Swift Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การจัดเก็บข้อมูลลับใน Keychain
  2. การควบคุมการเข้าถึง Keychain
  3. การยืนยันตัวตนด้วยข้อมูลชีวมิติ
  4. การปกป้องข้อมูลและการเข้ารหัส
← กลับไปที่ Swift Academy