React Native / Secure Storage

Secure Storage

AsyncStorage нь апп-н өгөгдлийг хадгалахад сайн боловч нууц мэдээлэл — token, нууц үг, хэрэглэгчийн мэдрэмжтэй өгөгдөл — хадгалахад тохиромжгүй. Учир нь AsyncStorage шифрлэгдээгүй тул root хийгдсэн Android утас дээр уншигдаж болно. expo-secure-store нь iOS-н Keychain, Android-н Keystore ашиглан өгөгдлийг шифрлэж хадгалдаг.

expo-secure-store суулгах

bash
npx expo install expo-secure-store

Суулгасны дараа restart хийхэд л бэлэн — нэмэлт тохируулга шаардлагагүй.

Үндсэн ашиглалт

SecureStore-н API маш энгийн — зөвхөн гурван үндсэн функц байдаг:

typescript
import * as SecureStore from "expo-secure-store";

// Хадгалах
await SecureStore.setItemAsync("user_token", "eyJhbGc...");

// Унших
const token = await SecureStore.getItemAsync("user_token");
console.log(token); // 'eyJhbGc...'

// Устгах
await SecureStore.deleteItemAsync("user_token");

Зөвхөн string хадгалдаг. Object хадгалах бол JSON.stringify хэрэглэнэ:

typescript
const user = { id: "123", name: "Болд", role: "admin" };

// Хадгалах
await SecureStore.setItemAsync("current_user", JSON.stringify(user));

// Унших
const raw = await SecureStore.getItemAsync("current_user");
const parsed = raw ? JSON.parse(raw) : null;

Custom hook — useSecureStorage

Дахин дахин нэг кодыг бичихгүйн тулд hook үүсгэх нь зөв арга:

typescript
import { useState, useEffect } from "react";
import * as SecureStore from "expo-secure-store";

export function useSecureStorage(key: string) {
  const [value, setValue] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    SecureStore.getItemAsync(key)
      .then(setValue)
      .finally(() => setLoading(false));
  }, [key]);

  async function save(newValue: string) {
    await SecureStore.setItemAsync(key, newValue);
    setValue(newValue);
  }

  async function remove() {
    await SecureStore.deleteItemAsync(key);
    setValue(null);
  }

  return { value, loading, save, remove };
}

Ашиглах нь маш тохиромжтой:

typescript
export default function ProfileScreen() {
  const { value: token, save, remove, loading } = useSecureStorage('auth_token');

  if (loading) return <Text>Ачааллаж байна...</Text>;

  return (
    <View>
      <Text>{token ? 'Нэвтэрсэн' : 'Нэвтрээгүй'}</Text>
      <TouchableOpacity onPress={() => save('new_token_value')}>
        <Text>Token хадгалах</Text>
      </TouchableOpacity>
      <TouchableOpacity onPress={remove}>
        <Text>Гарах</Text>
      </TouchableOpacity>
    </View>
  );
}

AsyncStorage vs SecureStore — хэзээ алийг ашиглах вэ?

Хоёр хадгалалтын аргыг зөв сонгох нь чухал:

| Өгөгдөл | Хэрэглэх арга | | --------------------- | -------------- | | Auth token, нууц үг | SecureStore | | API key | SecureStore | | Хэрэглэгчийн тохиргоо | AsyncStorage | | Апп-н state, cache | AsyncStorage | | Сүүлд үзсэн зүйл | AsyncStorage |

SecureStore-н хязгаарлалт: iOS дээр нэг утгын хэмжээ 2048 bytes хүртэл. Том өгөгдлийг шифрлэсэн хэлбэрээр өөр системд хадгалах хэрэгтэй.

Дараагийн хичээлд:

Deep Linking — бусад апп эсвэл вэбсайтаас таны аппыг нээж, тодорхой дэлгэцэд шууд очих холбоос хэрхэн тохируулах талаар сурна. Жишээлбэл, myapp://profile/123 гэсэн холбоос дарахад апп нээгдэж тухайн хэрэглэгчийн профайл харагдана.