본문 바로가기

공부/플러터\Flutter

[Flutter] FlutterSecureStorage 를 활용하여 로그인 상태유지, 로그아웃

반응형

왜 FlutterSecureStorage 를 사용하게 되었나?

모바일 어플리케이션에서 로그인을 하면 일반적으로 로그인 상태를 유지한다. 민감 정보들은 서버로 전송하여 데이터베이스에 암호화한 뒤 저장하는 것이 자연스럽다고 생각할 수 있다. 그러나 로그아웃하지 않는다면 또 다시 로그인을 하지 않게 해주는 편의를 제공하는 것이 필요하다. 그러면 로그인 정보를 어떻게 안전하게 저장할 수 있을까?

 

 

왜 보안에 취약한가?

- Android 에서의 문제

Android 는 루팅을 통해 루트 권한을 얻음으로 생산자, 판매자 측에서 걸어놓은 제약을 해제하면 SharedPreference 과 같이 쉽게 사용할 수 있는 내부 저장소들을 간단한 루팅 만으로 ADB(Android Debug Bridge)를 사용해서 저장되어 있는 내용을 쉽게 볼 수 있다고 한다.

 

어플리케이션을 껐다 다시 켰을때, 이전에 사용한 정보들을 저장해놓고 불러오기 위해서, 디바이스 기기 내부 디스크에 정보를 저장하는 shared_preferences(https://pub.dev/packages/shared_preferences) 패키지를 사용한다.

 

이 패키지는 주로 관리자 권한이 아니면 들어갈 수 없는 경로인 /data/data/패키지명/shared_prefs/SharedPreferences에 저장된다. 그러나 해당 단말기가 루팅을 하는 순간 저장된 SharedPreferences 경로로 접근이 가능해진다. 예를 들어 스마트폰이 악성코드에 감염되어서 루트권한이 탈취 당한다면, SharedPreferences에 저장된 중요 정보가 유출될 수 있기에 이를 사전에 방지하기 필요한다.

 

- iOS에서의 문제

iOS에서는 탈옥(Jailbreaking)을 통하여 iOS의 샌드박스 제한을 풀어 타 회사에서 사용하는 서명되지 않은 코드를 실핼할 수 있게 된다.

 

그래서 이러한 보안적 문제를 해결하기 위해 FlutterSecureStorage를 사용한다.

 

 

FlutterSecureStorage 란?

민감한 정보들을 저장할 때, flutter_secure_storage(https://pub.dev/packages/flutter_secure_storage)라는 패키지를 사용하면 Android에서는 keystore 영역에, iOS에서는 내부 저장소인 keychain 영역에 사용한다.

Android의 keystore은 소스코드 내부 어딘가가 아니라, 시스템만이 접근할 수 있는 컨테이너에 저장하기 때문에 루팅을 하여도 접근할 수 없다. 그래서 어플리케이션에서 임의로 발급한 암호화 키만 저장하고, 이 키를 이용하여 정보를 암호화해 로컬 DB에 저장하고, 저장된 정보를 사용할 때는 복호화하여 사용된다.

 

FlutterSecureStorage에 로그인 정보 저장 구현

ㄴpubspec.yaml 파일에 패키지 추가

1. pub add flutter_secure_storage

2. pub get

dependencies:
  flutter:
    sdk: flutter
  flutter_secure_storage: ^8.0.0

원하는 파일에 import package flutter_secure_storage 를 해준다! 

import 'package:flutter_secure_storage/flutter_secure_storage.dart';
# flutter_secure_storage 를 import 해준다.

 

 

login.dart 파일의 일부분 -  값 저장 방법

1. storage.write를 해주고, key값과 value값을 지정해준다.

  await storage.write(
      key: "login",
      value: "email " + emailController.text.toString() + " " +
          "password " + passwordController.text.toString() + " " +
          "session " + data);

 

login.dart 파일의 일부분 -  초기화 및 어떻게 값이 존재 유무 확인 방법

1.  FlutterSecureStorage() 를 storage 변수에 저장

2. initState()에 storage.read(key: [KEY값]) 함수를 사용하여 값이 기기에 저장되어 있는지 확인

...(생략)

static final storage = FlutterSecureStorage(); // FlutterSecureStorage를 storage로 저장

dynamic userInfo = ''; // storage에 있는 유저 정보를 저장
// dynamic 으로 한 이유?
// 아직 데이터들을 불러오지 않고, 선 선언 후 나중에 값을 저장하기 때문이다.



//flutter_secure_storage 사용을 위한 초기화
  @override
  void initState() {
    super.initState();

    // 비동기로 flutter secure storage 정보를 불러오기
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _asyncGetStorage();
    });
  }
  
    _asyncGetStorage() async {
    // read 함수로 key값에 맞는 정보를 불러오고 데이터타입은 String 타입
    // 데이터가 없을때는 null을 반환
    userInfo = await storage.read(key:'login');

    // user의 정보가 있는지 없는지에 따라서 로직을 나눌 수 있다.
    if (userInfo != null) {
      print('auto login success~');
    } else {
      print('login required');
    }
  }

 

 

FlutterSecureStorage에 로그아웃 구현

import 'package:flutter_secure_storage/flutter_secure_storage.dart'; // flutter_secure_storage 패키지

final storage = FlutterSecureStorage();

await storage.delete(key: 'login');

이렇게 해주면 된다! 아주 쉽다. 굳굳

반응형