RealmSwift: реализация однократного входа в систему с помощью MongoDB Realm в быстрой - PullRequest
1 голос
/ 04 августа 2020

Я хочу, чтобы пользователь входил в систему один раз, и ему не приходилось повторно вводить данные для входа каждый раз, когда они открывают приложение, если они не выходят из системы в последнем сеансе.

Экран входа в систему в настоящее время отображается каждый раз, когда приложение открыто. Это мой rootview

struct AppRootView: View {

     var body: some View {
        AnyView {
        
        // check if user has already logged in here and then route them accordingly 
        
            if auth.token != nil {
                homeMainView()
            } else {
                LoginController()
            }
        }
    }
}

в настоящее время это то, что я использую для входа пользователей

 @objc func signUp() {
        setLoading(true);
        app.usernamePasswordProviderClient().registerEmail(username!, password: password!, completion: {[weak self](error) in
            // Completion handlers are not necessarily called on the UI thread.
            // This call to DispatchQueue.main.sync ensures that any changes to the UI,
            // namely disabling the loading indicator and navigating to the next page,
            // are handled on the UI thread:
            DispatchQueue.main.sync {
                self!.setLoading(false);
                guard error == nil else {
                    print("Signup failed: \(error!)")
                    self!.errorLabel.text = "Signup failed: \(error!.localizedDescription)"
                    return
                }
                print("Signup successful!")
                
                // Registering just registers. Now we need to sign in, but we can reuse the existing username and password.
                self!.errorLabel.text = "Signup successful! Signing in..."
                self!.signIn()
            }
        })
    }

    @objc func signIn() {
        print("Log in as user: \(username!)");
        setLoading(true);
        
        app.login(withCredential: AppCredentials(username: username!, password: password!)) { [weak self](maybeUser, error) in
            
            DispatchQueue.main.sync {
                self!.setLoading(false);
                guard error == nil else {
                    // Auth error: user already exists? Try logging in as that user.
                    print("Login failed: \(error!)");
                    self!.errorLabel.text = "Login failed: \(error!.localizedDescription)"
                    return
                }
                
                guard let user = maybeUser else {
                    fatalError("Invalid user object?")
                }

                print("Login succeeded!");
                

//                
                let hostingController = UIHostingController(rootView: ContentView())
                self?.navigationController?.pushViewController(hostingController, animated: true)
            }

как я могу реализовать одноразовый вход, чтобы пользователям приходилось входить каждый раз, когда они открывают приложение?

Ответы [ 2 ]

1 голос
/ 13 августа 2020

Хотя использование Realm для сохранения входа в систему - это хорошая идея, но я настоятельно рекомендую не использовать ее для управления учетными данными пользователя, такими как пароли. Если вы хотите сохранить конфиденциальную информацию, лучший подход - использовать KeyChain, как это делают приложения Apple и менеджеры паролей. С помощью облегченной библиотеки оболочки keyChain, такой как SwiftKeychainWrapper , вы можете легко сохранить учетные данные для входа наиболее безопасным способом.

Вот пример использования оболочки keyChain, указанной выше.

С простой модификацией вы можете использовать этот вспомогательный класс для управления учетными данными для входа в любом месте вашего приложения.

import SwiftKeychainWrapper

class KeyChainService {

// Make a singleton
 static let shared = KeyChainService()

// Strings which will be used to map data in keychain
 private let passwordKey = "passwordKey"
 private let emailKey = "emailKey"
 private let signInTokenKey = "signInTokenKey"

// Saving sign in info to keyChain
    func saveUserSignInInformation(
        email: String,
        password: String,
        token: String
        onError: @escaping() -> Void,
        onSuccess: @escaping() -> Void
    ) {
        DispatchQueue.global(qos: .default).async {
            let passwordIsSaved: Bool = KeychainWrapper.standard.set(password, forKey: self.passwordKey)
            let emailIsSaved: Bool = KeychainWrapper.standard.set(email, forKey: self.emailKey)
           let tokenIsSaved: Bool = KeychainWrapper.standard.set(token, forKey: self.signInTokenKey)
            DispatchQueue.main.async {
                 // Verify that everything is saved as expected.
                if passwordIsSaved && emailIsSaved && tokenIsSaved {
                    onSuccess()
                }else {
                    onError()
                }
            }
        }
    }


// Retrieve signIn information for auto login
 func retrieveSignInInfo(onError: @escaping() -> Void, onSuccess: @escaping(UserModel) -> Void) {
        DispatchQueue.main.async {
            let retrievedPassword: String? = KeychainWrapper.standard.string(forKey: self.passwordKey)
            let retrievedEmail: String? = KeychainWrapper.standard.string(forKey: self.emailKey)
            let retrievedToken: String? = KeychainWrapper.standard.string(forKey: self.signInTokenKey)
                if let password = retrievedPassword,
                    let email = retrievedEmail,
                    let token = retrievedToken {
                    // Assuming that you have a custom user model named "UserModel"
                    let user = UserModel(email: email, password: password,token: token)
                     // Here is your user info which you can use to verify with server if needed and auto login user.
                    onSuccess(user)
                }else {
                    onError()
                }
            
        }
    }


}
0 голосов
/ 10 августа 2020

Правильно настроенный и инициализированный класс RealmApp сохранит информацию о сеансе для вас между перезапусками приложения, вы можете проверить существующий сеанс с помощью метода .currentUser() из этого класса. Итак, в вашем случае что-то вроде:

if app.currentUser() != nil {
    homeMainView()
} else {
    LoginController()
}
...