#c# #unity3d #firebase-authentication
#c# #unity3d #firebase-аутентификация
Вопрос:
Я настраиваю свою аутентификацию на firebase, и она работает очень хорошо. Однако, когда я загружаю другую сцену и после возврата к сцене приветствия, аутентификация завершается ошибкой. Что я должен сделать для повторной авторизации или сохранения входа в систему при смене сцен?
Мой код для сцены приветствия для авторизации:
public void Start()
{
InitializeFirebase();
InitializePlayGamesPlatform();
SignInPlayGames();
}
public void InitializeFirebase()
{
Debug.Log("UserManager: Setting up Firebase Auth");
auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
auth.StateChanged = AuthStateChanged;
auth.IdTokenChanged = IdTokenChanged;
// Specify valid options to construct a secondary authentication object.
if (otherAuthOptions != null amp;amp;
!(String.IsNullOrEmpty(otherAuthOptions.ApiKey) ||
String.IsNullOrEmpty(otherAuthOptions.AppId) ||
String.IsNullOrEmpty(otherAuthOptions.ProjectId)))
{
try
{
otherAuth = Firebase.Auth.FirebaseAuth.GetAuth(Firebase.FirebaseApp.Create(
otherAuthOptions, "Secondary"));
otherAuth.StateChanged = AuthStateChanged;
otherAuth.IdTokenChanged = IdTokenChanged;
}
catch (Exception)
{
Debug.Log("UserManager: ERROR: Failed to initialize secondary authentication object.");
}
}
AuthStateChanged(this, null);
}
public void InitializePlayGamesPlatform()
{
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder()
.RequestServerAuthCode(false)
.Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.Activate();
auth = FirebaseAuth.DefaultInstance;
}
public void SignInPlayGames()
{
connecting = true;
ServerConnectionStatus.GetComponent<Text>().text = "Connecting to PlayGames";
ServerConnectionStatus.GetComponent<Text>().color = Color.black;
Social.localUser.Authenticate((bool success) => {
if (!success)
{
Debug.LogError("UserManager: Failed to Sign in into PlayGames Service");
ServerConnectionStatus.GetComponent<Text>().text = "Cannot Connect to PlayGames";
ServerConnectionStatus.GetComponent<Text>().color = Color.red;
connecting = false;
return;
}
AuthCode = PlayGamesPlatform.Instance.GetServerAuthCode();
if (string.IsNullOrEmpty(AuthCode))
{
Debug.LogError("UserManager: Signed in into PlayGames Service, Failed to get Server Auth Code");
ServerConnectionStatus.GetComponent<Text>().text = "Cannot Connect to PlayGames";
ServerConnectionStatus.GetComponent<Text>().color = Color.red;
connecting = false;
return;
}
Debug.LogFormat("UserManager: Server Auth Code = {0}", AuthCode);
Credential credential = PlayGamesAuthProvider.GetCredential(AuthCode);
auth.SignInWithCredentialAsync(credential).ContinueWith(task => {
if (task.IsCanceled)
{
Debug.LogError("UserManager: SignInWithCredentialAsync was canceled.");
ServerConnectionStatus.GetComponent<Text>().text = "Cannot Sign in to PlayGames";
ServerConnectionStatus.GetComponent<Text>().color = Color.red;
task.Exception.ToString();
connecting = false;
return;
}
if (task.IsFaulted)
{
Debug.LogError("UserManager: SignInWithCredentialAsync encountered an error: " task.Exception);
ServerConnectionStatus.GetComponent<Text>().text = "Cannot Sign in to PlayGames";
ServerConnectionStatus.GetComponent<Text>().color = Color.red;
connecting = false;
return;
}
user = task.Resu<
Debug.LogFormat("UserManager: User signed in successfully: {0} ({1})",
user.DisplayName, user.UserId);
ServerConnectionStatus.GetComponent<Text>().text = "Connected to PlayGames";
ServerConnectionStatus.GetComponent<Text>().color = Color.green;
connected = true;
connecting = false;
nick = auth.CurrentUser.DisplayName;
SetPlayerName(nick);
});
});
}
public void SetPlayerName(string value)
{
PhotonNetwork.NickName = value;
PlayerPrefs.SetString("PlayerName", value);
}
void AuthStateChanged(object sender, System.EventArgs eventArgs)
{
Firebase.Auth.FirebaseAuth senderAuth = sender as Firebase.Auth.FirebaseAuth;
Firebase.Auth.FirebaseUser user = null;
if (senderAuth != null) userByAuth.TryGetValue(senderAuth.App.Name, out user);
if (senderAuth == auth amp;amp; senderAuth.CurrentUser != user)
{
bool signedIn = user != senderAuth.CurrentUser amp;amp; senderAuth.CurrentUser != null;
if (!signedIn amp;amp; user != null)
{
Debug.Log("UserManager: Signed out " user.UserId);
}
user = senderAuth.CurrentUser;
userByAuth[senderAuth.App.Name] = user;
if (signedIn)
{
Debug.Log("UserManager: Signed in " user.UserId);
displayName = user.DisplayName ?? "";
DisplayDetailedUserInfo(user, 1);
}
}
}
Ошибка результата:
04-01 01:37: 41.330: E / Unity (6065): UserManager: SignInWithCredentialAsync обнаружена ошибка: System.Исключение AggregateException: произошла одна или несколько ошибок.
—> Система.Исключение AggregateException: произошла одна или несколько ошибок.
—> Firebase.Исключение FirebaseException: предоставленные учетные данные для аутентификации неверно сформированы или срок их действия истек. [ Ошибка при получении токена доступа из playgames.google.com uri перенаправления OAuth2 равен:http://localhost , ответ: OAuth2TokenResponse{параметры: ошибка=invalid_grant amp;error_description=Неверный запрос, httpMetadata: HttpMetadata{статус=400, кэш-политика=NO_CACHE, Кэширование = null, cacheImmutable= false, staleWhileRevalidate=null, filename=null, LastModified = null, заголовки = HTTP /1.1 200 OK
Ответ №1:
Я много пробовал, но не получаю желаемого поведения (о повторной авторизации / приложение не завершается)
Даже если я меняю сцены, учетные данные остаются.
Если вы хотите сменить учетную запись,
повторно запустите приложение и затем выйдите из системы (facebook или Google) в сцене приветствия
Комментарии:
1. Спасибо за ваш ответ. Проблема в том, что когда я открываю сцену приветствия в первый раз и запрашиваю пользователя. DisplayName; это работает отлично. Когда я открываю другую сцену и после поворота обратно к сцене приветствия, пользователь. Displayname возвращает значение null. Когда я пытаюсь перезапустить функции firebase, он не выполняет вход и выдает указанную выше ошибку. Вы пробовали что-нибудь похожее на мой пример?
2. Кстати, я не хочу менять учетную запись, просто хочу, чтобы пользователь продолжал входить в систему.
3. Я не использую user. Отображаемое имя. Вы сделали этот класс одноэлементным? Если вам нужно displayname, сохраните в этом классе или Playerprefs
4. Я не пробовал singleton и не очень хорошо знаком с ним. Однако, если логика заключается в том, чтобы запустить его один раз, я уже пробовал это, удалив функции из start и выполнив их вручную. Есть ли какая-либо другая причина для singleton?
5. Я думаю, если вы хотите иметь информацию для аутентификации где угодно или существует только один класс, вам следует создать одноэлементный класс. и этот класс не должен быть уничтожен. Мой класс firebaseManager используется где угодно.
Ответ №2:
Предполагая, что в первый раз все работает так, как ожидалось, похоже, DontDestroyOnLoad
это то, что вы ищете:
Не уничтожает этот объект при переключении сцен -> следовательно, не запускает Start
метод повторно. Однако вам также потребуется объединить его с singleton
шаблоном, чтобы убедиться, что он не будет добавлен / запущен во второй раз при возвращении к этой первой сцене:
public class AuthComponent : MonoBehaviour
{
private static AuthComponent singleton;
private void Awake()
{
// Check if already another AuthComponent running
if(singleton)
{
Debug.Log("Already another AuthComponent running");
Destroy(gameObject);
return;
}
// Otherwise store a global reference of this AuthComponent
singleton = this;
// and make it DontDestroyOnLoad
DontDestroyOnLoad(gameObject);
}
...
}
Комментарии:
1. Большое спасибо за ответ. Должен ли я создать другой скрипт с приведенным выше кодом и добавить его в мой UserManager gameobject, где он содержит весь персонал аутентификации внутри? Извините, может быть, глупый вопрос, но я не знаком с этим :/
2. Например, да. Я не знал, как вызывается ваш класс. Вы также можете просто добавить это непосредственно в
UserManager
.3. Мне пока не удалось реализовать singleton, но после моего детального поиска singleton — это способ сделать это. Теперь у меня другие проблемы благодаря singleton 🙂 Я постараюсь их исправить, большое спасибо!