Swift Academy · Lektion

Lagring af hemmeligheder i Keychain

Gem og hent legitimationsoplysninger sikkert.

Lektion 1 af 413 trin

Lagring af hemmeligheder i Keychain er en gratis Swift Academy-lektion på CoddyKit. Dette er lektion 1 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Swift Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Swift Academy-kurset indeholder 4 lektioner i alt.

Hvorfor bruge Keychain

Adgangskoder, tokens og nøgler må aldrig ligge i UserDefaults eller almindelige filer — de er nemme at læse. Keychain er en krypteret database, der styres af operativsystemet, til små hemmeligheder og beskyttes af hardware og brugerens adgangskode. Det er det eneste korrekte sted til legitimationsoplysninger.

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

Elementer er ordbøger

Keychain Services API er C-baseret: Du beskriver et element med en forespørgselsordbog af typen [String: Any], der bruger konstante nøgler som kSec.... Den samme ordbogsstruktur genbruges til tilføjelse, søgning, opdatering og sletning.

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

Elementklasser

Nøglen kSecClass vælger elementtypen. kSecClassGenericPassword dækker appens tokens og hemmeligheder, mens kSecClassInternetPassword gemmer serverens legitimationsoplysninger med attributter for vært og protokol. De fleste apphemmeligheder bruger en generisk adgangskode.

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

Tilføjelse af et element

SecItemAdd indsætter et nyt element. Du inkluderer dataene under kSecValueData som Data samt attributter, der identificerer elementet. Metoden returnerer en OSStatus — errSecSuccess betyder, at det lykkedes.

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
}

Håndtering af dubletter

Hvis du tilføjer et element, hvis identifikationsattributter allerede findes, returneres errSecDuplicateItem. En robust gemmefunktion forsøger med SecItemAdd og bruger ved en dublet SecItemUpdate som reserve — et opret-eller-opdater-mønster.

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
}

Hentning af et element

SecItemCopyMatching søger. For at hente de hemmelige bytes skal du sætte kSecReturnData til true og kSecMatchLimit til kSecMatchLimitOne. Resultatet returneres via en outputparameter som 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
}

Opdatering af et element

SecItemUpdate tager to ordbøger: en forespørgsel, der finder elementet, og en ordbog med attributter, der skal opdateres. Kun de attributter, du angiver, ændres; alt andet bevares.

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
}

Sletning af et element

SecItemDelete fjerner matchende elementer. Sletning af noget, der ikke findes, returnerer errSecItemNotFound, hvilket du kan behandle som en succes, når du rydder legitimationsoplysninger ved logout.

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
}

Afkodning af OSStatus

Fejl angives som heltalskoder af typen OSStatus. SecCopyErrorMessageString omdanner en sådan kode til en beskrivelse, der er let at læse, hvilket er uvurderligt ved fejlsøgning af, hvorfor en lagring eller læsning mislykkedes.

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

Entydig identifikation af elementer

Elementer matches ud fra kombinationen af deres attributter — typisk kSecAttrService plus kSecAttrAccount for generiske adgangskoder. Vælg en stabil, app-specifik tjenestestreng, så forskellige hemmeligheder aldrig kolliderer.

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)

En lille indpakning

Fordi den rå API er omstændelig, indpakker teams den i en lille type, der eksponerer save, read og delete. Det holder kSec-ceremonien samlet ét sted og gør kaldestederne overskuelige.

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
    }
}

Hurtigt tjek

Husk den korrekte måde at hente bytes fra en gemt hemmelighed på.

Opsummering

Du har lært CRUD i Keychain:

  • Gem legitimationsoplysninger i den krypterede Keychain, aldrig i UserDefaults eller filer.
  • Beskriv elementer med kSec-forespørgselsordbøger; vælg en klasse som kSecClassGenericPassword.
  • SecItemAdd / SecItemCopyMatching / SecItemUpdate / SecItemDelete dækker livscyklussen; håndtér errSecDuplicateItem med en upsert.
  • Identificér elementer med tjeneste + konto, og afkod OSStatus ved fejlsøgning.
Gratis at komme i gang

Lær Swift med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
122
Lektioner
409

Ofte stillede spørgsmål

Er lektionen “Lagring af hemmeligheder i Keychain” gratis?

Ja — alle 3 lektioner i læringssporet Swift Academy, inklusive “Lagring af hemmeligheder i Keychain”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Swift Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “Lagring af hemmeligheder i Keychain”?

Gem og hent legitimationsoplysninger sikkert. Du øver dig i Swift Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Swift Academy?

Der kræves ingen tidligere erfaring. Swift Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 1 af 4.

Hvor lang tid tager lektionen “Lagring af hemmeligheder i Keychain”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Swift Academy-lektion?

Ja. Alle Swift Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Lagring af hemmeligheder i Keychain
  2. Adgangskontrol til Keychain
  3. Biometrisk godkendelse
  4. Databeskyttelse og kryptering
← Tilbage til Swift Academy