Repository navigation
Storage fr
🌐 Cette page en : English · Português · Español · Français · Deutsch
Une signature par-dessus le magasin natif propre à chaque plateforme. Une application écrit le même C# partout, et la valeur atterrit là où cette plateforme garde déjà ce genre de chose, si bien que sa sauvegarde, sa migration et sa désinstallation se comportent comme un utilisateur s'y attend, sans que le framework invente ou embarque quoi que ce soit.
Depuis 0.2.0-preview.10
Il y a deux interfaces, et laquelle vous prenez est une décision, pas un paramètre.
IAppStorage |
ISecretStore |
|
|---|---|---|
| Web | localStorage |
aucun, se résout à null |
| macOS / iOS | NSUserDefaults |
Keychain |
| Android | SharedPreferences |
AES/GCM adossé au KeyStore |
Les deux se prennent par constructeur, comme toute autre capacité :
public sealed class SettingsShell(IAppStorage storage) : StatefulComponent
{
private void Remember(string language) => storage.Set("language", language);
}Chaque cible. En natif, le conteneur .NET le résout ; dans le navigateur, le constructeur transpilé le résout par le nom de l'interface ; pendant le SSR il se résout à un magasin qui ne contient rien et le dit : les lectures répondent
null, les écritures ne vont nulle part, parce que le stockage que ceci représente vit sur la machine de la visiteuse. Donc une page lit sa valeur stockée au premier rendu du client, et le balisage rendu côté serveur montre la même chose qu'une toute première visite. Voir Capacités pour le tableau complet.
Lisez-le dans
OnMount, pas dans le constructeur : le réconciliateur construit des instances neuves à chaque passe et garde celle qui est retenue, donc un constructeur qui lit le stockage le relit pour une instance qui est ensuite jetée. (Composants write-once)
Mettre un jeton dans localStorage est l'erreur de sécurité la plus commise sur le web, et une API
où la sûreté est un argument secure: true est une API où la sûreté est à un argument oublié près.
Ici le choix ne peut pas se faire par omission : un secret demande un service différent, et le
demander est quelque chose que quelqu'un a fait exprès.
Le navigateur n'a pas de coffre, donc sur le web ISecretStore se résout à null, de la même
façon que le framework rapporte chaque capacité qu'un hôte n'a pas, plutôt que de faire semblant avec
un magasin que n'importe quel script de l'origine peut lire. Une application qui le cherche sur le web
doit répondre à la question qu'elle évitait : garder le secret sur le serveur et remettre au navigateur
une session qu'il ne peut que dépenser, ou accepter que ce qu'elle stockait n'a jamais vraiment été un
secret.
En natif, c'est le vrai coffre de la plateforme. Apple : un élément kSecClassGenericPassword par clé
sous l'identifiant de bundle de l'application, AfterFirstUnlockThisDeviceOnly pour qu'un
rafraîchissement en arrière-plan puisse le lire tandis qu'un appareil non déverrouillé depuis le
démarrage ne peut pas, et jamais synchronisé vers iCloud. Android : une clé AES adossée au matériel
dans AndroidKeyStore (le matériau de la clé est illisible même pour ce processus) avec un
chiffré AES/GCM dans un fichier de préférences. C'est ce que fait
EncryptedSharedPreferences d'AndroidX, écrit directement parce que la plateforme livre chaque pièce
et que le framework ne prend pas de dépendance pour quelque chose que l'OS fournit déjà.
Chaque magasin ici est une carte de chaînes en dessous. Une surface typée serait trois sérialiseurs à maintenir identiques, et leur premier désaccord est une valeur qui s'écrit sur une plateforme et ne se lit pas sur une autre. Sérialisez dans votre application, là où le format est le vôtre.
Il n'y a pas de réalisation serveur. Pendant le SSR le service se résout à null et les lectures
ne répondent rien.
Cela compte plus qu'il n'y paraît. Une page qui branche son arbre sur un état stocké rend une chose sur le serveur et une autre dans le navigateur, et le réconciliateur réconciliera fidèlement la différence sous les yeux de la lectrice. Lisez le stockage dans un gestionnaire d'événement ou après le mount, jamais pendant la construction.
C'est aussi pourquoi le stockage seul ne peut pas se souvenir d'un thème sans un clignotement : le
serveur peint d'abord et localStorage n'est pas quelque chose qu'il peut voir. Ce problème précis
veut un cookie, parce que l'exigence n'est pas "se souvenir" mais "dire au serveur", et le framework
s'en occupe déjà, donc une application n'a pas à le faire. Voir
ServerIntegration.
-
localStorageest l'API du DOM la plus susceptible de lever plutôt que d'échouer discrètement. Le mode privé de Safari a levé à l'écriture, un navigateur à son quota lève, et le lire tout court lève quand l'origine a le stockage bloqué. Une préférence qui n'arrive pas à s'enregistrer ne doit pas faire tomber une page, donc une écriture qui ne peut pas avoir lieu n'a simplement pas lieu, et une lecture qui ne peut pas avoir lieu répondnull. - Un élément de Keychain ne survit pas à toute restauration, et une clé de KeyStore est invalidée par un nouvel écran de verrouillage. Les deux rendent chaque valeur sous elles définitivement illisible.
Traitez donc une lecture null comme un "redemande" (reconnecte-toi, retombe sur la valeur par
défaut) et jamais comme une erreur à rapporter. C'est la même réponse que donne une clé qui n'a jamais
été écrite, et l'appelant gère déjà celle-là.
Chaque capacité est enregistrée avec TryAdd, donc enregistrer le vôtre gagne :
builder.Services.AddSingleton<IAppStorage, MyOwnStorage>();C'est l'échappatoire pour un magasin à la durabilité différente, un fichier chiffré ou un double de test.
🏁 Commencer ici
🏗️ Architecture
- Vue d'ensemble de l'architecture
- Composants write-once
- Surface déclarative
- Architecture des paquets
- Composants
- Styles
- Localisation
- Analytics et GTM
📱 Write-once
- Moteur Photon
- Design System
- Capacités
- Stockage
- Formulaires
- Éditeur de code
- Markdown
- Mermaid
- Rendu des e-mails
⚙️ Compilation
- Compilateur
- Fonctionnalités C# prises en charge
- Résolution des types externes
- Flux de build
- Diagnostics
⚡ Runtime
🔌 Serveur
🎨 Écosystème
- Image · Graphiques · Icônes · Lottie
🚀 Développement