Unabhängig davon, ob Sie eine mobile Anwendung oder einen Web-Service erstellen, ist es wichtig, sensible Daten zu schützen, und Sicherheit ist zu einem wesentlichen Bestandteil jedes Softwareprodukts geworden. In diesem Lernprogramm werde ich Ihnen zeigen, wie Sie Benutzeranmeldeinformationen mithilfe des Schlüsselbunds der Anwendung sicher speichern. Wir werden uns mit dem Ver- und Entschlüsseln von Benutzerdaten mithilfe einer Drittanbieter-Bibliothek befassen.
In diesem Tutorial werde ich Ihnen zeigen, wie Sie sensible Daten auf der iOS-Plattform schützen. Vertrauliche Daten können Anmeldeinformationen eines Benutzers oder Kreditkartendaten sein. Die Art der Daten ist nicht so wichtig. In diesem Lernprogramm verwenden wir den iOS-Schlüsselbund und die symmetrische Verschlüsselung, um die Daten des Benutzers sicher zu speichern. Bevor wir uns mit den wichtigsten Details befassen, möchte ich Ihnen einen Überblick darüber geben, was wir in diesem Tutorial tun werden.
Obwohl sich dieses Tutorial auf iOS konzentriert, können die Konzepte und Techniken auch unter OS X verwendet werden.Unter iOS und OS X ist ein Schlüsselbund ein verschlüsselter Container zum Speichern von Kennwörtern und anderen Daten, die gesichert werden müssen. Unter OS X ist es möglich, den Schlüsselbundzugriff auf bestimmte Benutzer oder Anwendungen zu beschränken. Unter iOS hat jede Anwendung jedoch einen eigenen Schlüsselbund, auf den nur die Anwendung Zugriff hat. Dadurch wird sichergestellt, dass die im Schlüsselbund gespeicherten Daten für Dritte sicher und nicht zugänglich sind.
Beachten Sie, dass der Schlüsselbund nur zum Speichern kleiner Daten wie Passwörter verwendet werden sollte. Mit diesem Artikel hoffe ich, Sie davon zu überzeugen, wie wichtig es ist, den Schlüsselbund unter iOS und OS X zu verwenden, anstatt beispielsweise die Benutzer-Standarddatenbank der Anwendung, die ihre Daten ohne jegliche Sicherheit im Klartext speichert.
Unter iOS kann eine Anwendung den Schlüsselbund über die verwenden Keychain Services-API. Die API bietet eine Reihe von Funktionen zum Bearbeiten der im Schlüsselbund der Anwendung gespeicherten Daten. Sehen Sie sich die unter iOS verfügbaren Funktionen an.
SecItemAdd
Mit dieser Funktion wird ein Element zum Schlüsselbund der Anwendung hinzugefügt.SecItemCopyMatching
Mit dieser Funktion können Sie einen Schlüsselbundartikel finden, der der Anwendung gehört.SecItemDelete
Wie der Name schon sagt, kann mit dieser Funktion ein Element aus dem Schlüsselbund der Anwendung entfernt werden.SecItemUpdate
Verwenden Sie diese Funktion, wenn Sie ein Element im Schlüsselbund der Anwendung aktualisieren möchten.Das Keychain Services-API ist eine C-API, aber ich hoffe, dass Sie nicht daran gehindert werden. Jede der oben genannten Funktionen akzeptiert ein Wörterbuch (CFDictionaryRef
), die ein Elementklassenschlüsselwertpaar und optionale Attributschlüsselwertpaare enthält. Die genaue Bedeutung und der Zweck von jedem wird klar, sobald wir die API in einem Beispiel verwenden.
Wenn Sie über die Verschlüsselung sprechen, hören Sie im Allgemeinen zwei Arten der Verschlüsselung, symmetrisch und asymmetrisch Verschlüsselung. Symmetrische Verschlüsselung verwendet einerseits einen gemeinsamen Schlüssel zum Verschlüsseln und Entschlüsseln von Daten. Die asymmetrische Verschlüsselung hingegen verwendet einen Schlüssel zum Verschlüsseln von Daten und einen anderen separaten, jedoch verwandten Schlüssel zum Entschlüsseln von Daten.
In diesem Tutorial nutzen wir die Sicherheitsrahmen Auf iOS verfügbar, um Daten zu verschlüsseln und zu entschlüsseln. Dieser Prozess findet unter der Haube statt, sodass wir nicht direkt mit diesem Framework interagieren. In unserer Beispielanwendung verwenden wir symmetrische Verschlüsselung.
Das Sicherheitsrahmen bietet eine Reihe weiterer Dienste an, z. B. Randomization-Dienste zum Generieren kryptographisch sicherer Zufallszahlen, Zertifikat, Schlüssel und Vertrauensdienste zum Verwalten von Zertifikaten, öffentlichen und privaten Schlüsseln sowie Vertrauensrichtlinien. Das Sicherheitsrahmen ist ein einfaches Framework, das sowohl für iOS als auch für OS X mit C-basierten APIs verfügbar ist.
In diesem Lernprogramm werde ich Ihnen zeigen, wie Sie die Keychain Services-API und die symmetrische Verschlüsselung in einer iOS-Anwendung verwenden können. Wir erstellen eine kleine Anwendung, die vom Benutzer aufgenommene Fotos sicher speichert.
In diesem Projekt verwenden wir Sam Soffes SSKeychain, einen Objective-C-Wrapper für die Interaktion mit der Keychain Services-API. Zur Ver- und Entschlüsselung verwenden wir RNCryptor, eine Verschlüsselungsbibliothek eines Drittanbieters.
Die RNCryptor-Bibliothek ist eine gute Wahl zum Verschlüsseln und Entschlüsseln von Daten. Das Projekt wird von vielen Entwicklern verwendet und von seinen Erstellern aktiv gepflegt. Die Bibliothek bietet eine einfach zu verwendende Objective-C-API. Wenn Sie mit Cocoa und Objective-C vertraut sind, ist die Verwendung einfach. Die Hauptfunktionen der Bibliothek sind unten aufgeführt.
Bevor wir mit dem Erstellen der Anwendung beginnen, möchte ich Ihnen zeigen, wie der typische Ablauf der Anwendung aussehen wird.
Starten Sie Xcode und erstellen Sie ein neues Projekt, indem Sie die Option auswählen Einzelansicht-Anwendung Vorlage aus der Liste der Vorlagen.
Nennen Sie das Projekt Sichere Fotos und setzen Gerätefamilie auf das iPhone. Teilen Sie Xcode mit, wo Sie das Projekt speichern möchten, und klicken Sie auf Erstellen.
Der nächste Schritt ist die Verknüpfung des Projekts mit der Sicherheit und Mobile Core Services Rahmenbedingungen. Wählen Sie das Projekt in der Projektnavigator Wählen Sie links das erste benannte Ziel aus Sichere Fotos, und öffnen Sie die Baue Phasen Tab oben. Erweitere die Binäres mit Bibliotheken verknüpfen Schublade und verknüpfen das Projekt gegen die Sicherheit und Mobile Core Services Rahmenbedingungen.
Wie bereits erwähnt, werden wir die SSKeychain-Bibliothek und die RNCryptor-Bibliothek verwenden. Laden Sie diese Abhängigkeiten herunter und fügen Sie sie dem Projekt hinzu. Kopieren Sie die Dateien in Ihr Projekt und fügen Sie sie dem hinzu Sichere Fotos Ziel wie in der Abbildung unten gezeigt.
Wir zeigen die Fotos des Benutzers in einer Sammlungsansicht an, das heißt, wir müssen eine Unterklasse erstellen UICollectionViewController
ebenso gut wie UICollectionViewCell
. Wählen Neu> Datei… von dem Datei Erstellen Sie eine Unterklasse von UICollectionViewController
, und nennen Sie es MTPhotosViewController
. Wiederholen Sie diesen Schritt noch einmal für MTPhotoCollectionViewCell
, das ist eine Unterklasse von UICollectionViewCell
.
Öffnen Sie das Haupt-Storyboard des Projekts und aktualisieren Sie das Storyboard wie in der Abbildung unten gezeigt. Das Storyboard enthält zwei Ansichtscontroller, eine Instanz von MTViewController
, enthält zwei Textfelder und eine Schaltfläche sowie eine Instanz von MTPhotosViewController
. Das MTViewController
Instanz ist in einen Navigationscontroller eingebettet.
Wir müssen auch ein Segment von der erstellen MTViewController
Instanz zum MTPhotosViewController
Beispiel. Legen Sie die ID des Segues auf fest photosViewController
. Das MTPhotosViewController
Die Instanz sollte auch einen Bar-Button enthalten, wie in der Abbildung unten gezeigt.
Damit dies funktioniert, müssen wir die Benutzeroberfläche von aktualisieren MTViewController
Wie nachfolgend dargestellt. Wir deklarieren für jedes Textfeld einen Ausgang und eine Aktion, die durch die Schaltfläche ausgelöst wird. Stellen Sie die erforderlichen Verbindungen im Haupt-Storyboard des Projekts her.
#einführen@interface MTViewController: UIViewController @property (schwach, nicht atomar) IBOutlet UITextField * usernameTextField; @ property (schwach, nicht atomar) IBOutlet UITextField * passwordTextField; - (IBAction) Login: (ID) Absender; @Ende
In dem MTPhotosViewController
Klasse, deklarieren Sie eine Eigenschaft namens Nutzername
zum Speichern des Benutzernamens des aktuell angemeldeten Benutzers und zum Deklarieren einer Aktion für das Element der Bar-Schaltfläche. Vergessen Sie nicht, die Aktion mit dem Bar-Button-Element im Haupt-Storyboard zu verbinden.
#einführen@Interface MTPhotosViewController: UICollectionViewController @property (Kopie, nicht atomar) NSString * Benutzername; - (IBAction) -Fotos: (ID) -Sender; @Ende
MTViewController
Im MTViewController.m
, Fügen Sie eine Importanweisung für die hinzu MTPhotosViewController
Klasse, die SSKeychain
Klasse und die MTAppDelegate
Klasse. Wir passen auch die an MTViewController
Klasse zum UIAlertViewDelegate
Protokoll.
#import "MTViewController.h" #import "SSKeychain.h" #import "MTAppDelegate.h" #import "MTPhotosViewController.h" @interface MTViewController ()@Ende
Der nächste Schritt ist die Implementierung der Anmeldung:
Aktion, die wir früher erklärt haben Wir prüfen zunächst, ob der Benutzer bereits ein Konto erstellt hat, indem Sie das Kennwort für das Konto abrufen. Ist dies der Fall, verwenden wir den Schlüsselbund der Anwendung, um festzustellen, ob das vom Benutzer eingegebene Kennwort mit dem im Schlüsselbund gespeicherten Kennwort übereinstimmt. Die von der SSKeychain Die Bibliothek erleichtert das Lesen und Bearbeiten von Daten, die im Schlüsselbund der Anwendung gespeichert sind.
- (IBAction) login: (id) sender if (self.usernameTextField.text.length> 0 && self.passwordTextField.text.length> 0) NSString * password = [SSKeychain passwordForService: @ "MyPhotos" -Konto: self.usernameTextField .Text]; if (password.length> 0) if ([self.passwordTextField.text isEqualToString: password]) [self performSegueWithIdentifier: @ "photosViewController" sender: nil]; else UIAlertView * alertView = [[UIAlertView-Zuordnung] initWithTitle: @ Meldung "Fehleranmeldung": @ "Ungültige Kombination aus Benutzername und Kennwort." Delegat: nil cancelButtonTitle: @ "OK" otherButtonTitles: nil]; [alertView show]; else UIAlertView * alertView = [[UIAlertView-Zuordnung] initWithTitle: @ Meldung "Neues Konto": @ "Möchten Sie ein Konto erstellen?" Delegat: self cancelButtonTitle: @ "Cancel" otherButtonTitles: @ "OK", nil]; [alertView show]; else UIAlertView * alertView = [[UIAlertView-Zuordnung] initWithTitle: @ Meldung "Error Input": @ "Benutzername und / oder Kennwort dürfen nicht leer sein." Delegat: nil cancelButtonTitle: @ "OK" otherButtonTitles: nil]; [alertView show];
Wir haben den Ansichtscontroller als Delegierten der Warnungsansicht festgelegt, was bedeutet, dass wir den implementieren müssen UIAlertViewDelegate
Protokoll. Schauen Sie sich die Implementierung von an alertView: clickedButtonAtIndex:
unten gezeigt.
-(void) alertView: (UIAlertView *) alertView clickedButtonAtIndex: (NSInteger) buttonIndex switch (buttonIndex) case 0: break; Fall 1: [self createAccount]; brechen; Standard: Pause;
Im Benutzerkonto anlegen
, wir nutzen die SSKeychain
Klasse, um den vom Benutzer gewählten Benutzernamen und das Kennwort sicher zu speichern. Wir rufen dann an performSegueWithIdentifier: Absender:
.
- (void) createAccount BOOL result = [SSKeychain setPassword: self.passwordTextField.text forService: @ "MyPhotos" -Konto: self.usernameTextField.text]; if (Ergebnis) [self performSegueWithIdentifier: @ "photosViewController" sender: nil];
Im prepareForSegue: Absender:
, Wir bekommen einen Hinweis auf die MTPhotosViewController
Beispiel, setzen Sie seine Nutzername
Eigenschaft mit dem Wert von BenutzernameTextField
, und setzen Sie das zurück passwordTextField
.
- (void) prepareForSegue: (UIStoryboardSegue *) Absender Absender: (ID) Absender MTPhotosViewController * photosViewController = segue.destinationViewController; photosViewController.username = self.usernameTextField.text; self.passwordTextField.text = nil;
MTPhotosCollectionViewCell
Öffnen MTPhotosCollectionViewCell.h und deklarieren Sie eine Filiale mit dem Namen Bildansicht
vom Typ UIImageView
.
#einführen@Interface MTPhotoCollectionViewCell: UICollectionViewCell @property (schwach, nicht atomar) IBOutlet UIImageView * imageView; @Ende
Öffne das Haupt-Storyboard und füge eine hinzu UIImageView
Beispiel zur Prototypzelle der MTPhotosViewController
Beispiel. Wählen Sie die Prototypzelle (nicht die Bildansicht) aus und setzen Sie ihre Klasse auf MTPhotosCollectionViewCell
in dem Identitätsinspektor zur Rechten. Öffnen Sie bei noch markierter Prototypzelle die Attribute-Inspektor und setzen Sie den Bezeichner auf Fotozelle
.
MTPhotosViewController
Importieren Sie zunächst die erforderlichen Header-Dateien in MTPhotosViewController.m Wie nachfolgend dargestellt. Wir müssen auch zwei Eigenschaften angeben, Fotos
Zum Speichern des Arrays von Fotos werden in der Sammlungsansicht und angezeigt Dateipfad
um einen Verweis auf den Dateipfad zu behalten. Sie haben vielleicht bemerkt, dass die MTPhotosViewController
Klasse entspricht der UIActionSheetDelegate
, UINavigationControllerDelegate
, und UIImagePickerControllerDelegate
Protokolle.
#import "MTPhotosViewController.h" #import#import "RNDecryptor.h" #import "RNEncryptor.h" #import "MTPhotoCollectionViewCell.h" @interface MTPhotosViewController () @ Eigenschaft (stark, nichtatomisch) NSMutableArray * -Fotos; @ property (copy, nonatomic) NSString * filePath; @Ende
Ich habe auch eine Komfort- oder Hilfsmethode implementiert, setupUserDirectory
, zum Erstellen und Einrichten der erforderlichen Verzeichnisse, in denen die Benutzerdaten gespeichert werden. Im bereiten Sie Daten vor
, Die Anwendung entschlüsselt die Bilder, die im sicheren Verzeichnis des Benutzers gespeichert sind. Sehen Sie sich die Implementierungen unten an.
- (void) setupUserDirectory NSArray * pfade = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); NSString * documents = [pfade objectAtIndex: 0]; self.filePath = [Dokumente stringByAppendingPathComponent: self.username]; NSFileManager * fileManager = [NSFileManager defaultManager]; if ([fileManager fileExistsAtPath: self.filePath]) NSLog (@ "Verzeichnis bereits vorhanden."); else NSError * error = nil; [fileManager createDirectoryAtPath: self.filePath withIntermediateDirectories: YES-Attribute: keine Fehler: & Fehler]; if (error) NSLog (@ "Verzeichnis für Benutzer kann nicht erstellt werden.");
- (void) prepareData self.photos = [[NSMutableArray Allocation] init]; NSFileManager * fileManager = [NSFileManager defaultManager]; NSError * error = nil; NSArray * contents = [fileManager contentsOfDirectoryAtPath: Self.filePath-Fehler: & Fehler]; if ([Inhaltszähler] &&! -Fehler) NSLog (@ "Inhalt des Benutzerverzeichnisses.% @", Inhalt); for (NSString * fileName im Inhalt) if ([fileName rangeOfString: @ ". protectedData"]. length> 0) NSData * data = [NSData dataWithContentsOfFile: [self.filePath stringByAppendingPathComponent: fileName]]; NSData * decryptedData = [RNDecryptor decryptData: data withSettings: kRNCryptorAES256Einstellungspasswort: @ "A_SECRET_PASSWORD" Fehler: nil]; UIImage * image = [UIImage imageWithData: decryptedData]; [self.photos addObject: Bild]; else NSLog (@ "Diese Datei ist nicht gesichert."); else if (! [Inhaltsanzahl]) if (Fehler) NSLog (@ "Der Inhalt des Benutzerverzeichnisses kann nicht gelesen werden."); else NSLog (@ "Das Verzeichnis des Benutzers ist leer.");
Rufen Sie beide Methoden in den View-Controllern auf viewDidLoad
Methode wie unten gezeigt.
- (void) viewDidLoad [super viewDidLoad]; [self setupUserDirectory]; [Selbstvorbereitungsdaten];
Die Bar-Schaltfläche in der Navigationsleiste des View-Controllers zeigt ein Aktionsblatt, in dem der Benutzer zwischen der Kamera des Geräts und der Fotobibliothek wählen kann.
- (IBAction) photos: (id) sender UIActionSheet * actionSheet = [[UIActionSheet-Zuordnung] initWithTitle: @ "Quelle auswählen" delegieren: self cancelButtonTitle: @ "Abbrechen" destructiveButtonTitle: nil otherButtonTitles: @ "Camera", @ "Photo Library" null]; [actionSheet showFromBarButtonItem: Sender animiert: JA];
Lass uns implementieren actionSheet: clickedButtonAtIndex:
des UIActionSheetDelegate
Protokoll.
- (void) actionSheet: (UIActionSheet *) actionSheet clickedButtonAtIndex: (NSInteger) buttonIndex if (buttonIndex.) < 2) UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init]; imagePickerController.mediaTypes = @[(__bridge NSString *)kUTTypeImage]; imagePickerController.allowsEditing = YES; imagePickerController.delegate = self; if (buttonIndex == 0) #if TARGET_IPHONE_SIMULATOR #else imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera; #endif else if ( buttonIndex == 1) imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; [self.navigationController presentViewController:imagePickerController animated:YES completion:nil];
Um die Auswahl des Benutzers in der Image Picker-Steuerung zu handhaben, müssen wir implementieren imagePickerController: didFinishPickingMediaWithInfo:
des UIImagePickerControllerDelegate
Protokoll wie unten gezeigt. Das Bild wird mit verschlüsselt encryptData
des RNEncryptor
Bibliothek. Das Bild wird auch dem hinzugefügt Fotos
Array und die Sammlungsansicht wird neu geladen.
- (void) imagePickerController: (UIImagePickerController *) - Auswahlfeld didFinishPickingMediaWithInfo: (NSDictionary *) info UIImage * image = [info objectForKey: UIImagePickerControllerEditedImage]; if (! image) [info objectForKey: UIImagePickerControllerOriginalImage]; NSData * imageData = UIImagePNGRepresentation (image); NSString * imageName = [NSString stringWithFormat: @ "image-% d.securedData", self.photos.count + 1]; NSData * encryptedImage = [RNEncryptor encryptData: imageData withSettings: kRNCryptorAES256Settings-Kennwort: @ "A_SECRET_PASSWORD" Fehler: nil]; [encryptedImage writeToFile: [self.filePath stringByAppendingPathComponent: imageName] atomisch: YES]; [self.photos addObject: Bild]; [self.collectionView reloadData]; [picker dismissViewControllerAnimated: YES completion: nil];
Bevor Sie die Anwendung erstellen und ausführen können, müssen Sie das implementieren UICollectionViewDataSource
Protokoll wie unten gezeigt.
- (NSInteger) collectionView: (UICollectionView *) collectionView numberOfItemsInSection: (NSInteger) Abschnitt return self.photos? self.photos.count: 0;
- (UICollectionViewCell *) collectionView: (UICollectionView *) collectionView cellForItemAtIndexPath: (NSIndexPath *) indexPath MTPhotoCollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier: @ "PhotoCell" fürIndexPath: cell.imageView.image = [self.photos objectAtIndex: indexPath.row]; zurück Zelle;
Wenn die Anwendung in den Hintergrund wechselt, muss der Benutzer abgemeldet werden. Dies ist aus Sicherheitsgründen wichtig. Um dies zu erreichen, muss der Anwendungsdelegierte über einen Verweis auf den Navigationscontroller verfügen, damit er in den Root-View-Controller des Navigationsstapels gelangen kann. Beginnen Sie mit der Deklaration einer Eigenschaft namens navigationController
im MTAppDelegate.h.
#einführen@Interface MTAppDelegate: UIResponder @ property (strong, nonatomic) UIWindow * -Fenster; @ property (strong, nonatomic) UINavigationController * navigationController; @Ende
In der Ansicht Controller viewDidLoad
Als Methode legen wir die Anwendungsdelegaten fest navigationController
Eigenschaft wie unten gezeigt. Denken Sie daran, dass dies nur eine Möglichkeit ist, damit umzugehen.
Ich habe die obige Eigenschaft in eingestellt ViewController's
viewDidLoad
Methode wie unten gezeigt.
- (void) viewDidLoad [super viewDidLoad]; MTAppDelegate * applicationDeleagte = (MTAppDelegate *) [[UIApplication sharedApplication] -Delegat]; [applicationDeleagte setNavigationController: self.navigationController];
Im Anwendungsdelegierten müssen wir aktualisieren applicationWillResignActive:
Wie nachfolgend dargestellt. So einfach ist das. Das Ergebnis ist, dass der Benutzer abgemeldet wird, wenn die Anwendung den Fokus verliert. Dadurch werden die in der Anwendung gespeicherten Bilder des Benutzers vor neugierigen Blicken geschützt. Der Nachteil ist, dass sich der Benutzer anmelden muss, wenn die Anwendung wieder aktiv wird.
- (void) applicationWillResignActive: (UIApplication *) Anwendung [self.navigationController popToRootViewControllerAnimated: NO];
Erstellen Sie das Projekt und führen Sie die Anwendung aus, um es auf Herz und Nieren zu testen.
In diesem Lernprogramm haben Sie gelernt, wie Sie die Keychain Services-API zum Speichern vertraulicher Daten verwenden. Außerdem haben Sie erfahren, wie Sie Bilddaten unter iOS verschlüsseln. Hinterlassen Sie einen Kommentar in den Kommentaren, wenn Sie Fragen oder Anregungen haben.