Авторизация

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

Откройте демо сцену MasterServerAndClient, которая находится в папке MasterServerToolkit -> Demos -> BasicAuthorization -> Scenes -> MasterServerAndClient. В этой сцене все настроено для того, чтобы увидеть как работает система авторизации и протестировать это на деле.

Выберите --CLIENT_MANAGER и откройте привязанный к нему компонент AuthBehaviour. Данный компонент содержит все основные методы для работы с авторизацией. 

protected override void OnInitialize()
{
    Mst.Events.Invoke(MstEventKeys.showLoadingInfo, "Connecting to master... Please wait!");

    FindOrCreateMasterConnector();

    // If we want to use default credentials for signin or signup views
    if (useDefaultCredentials && Mst.Runtime.IsEditor)
    {
        var credentials = new MstProperties();
        credentials.Set(MstDictKeys.userName, defaultUsername);
        credentials.Set(MstDictKeys.userPassword, defaultPassword);
        credentials.Set(MstDictKeys.userEmail, defaultEmail);

        Mst.Events.Invoke(MstEventKeys.setSignInDefaultCredentials, credentials);
        Mst.Events.Invoke(MstEventKeys.setSignUpDefaultCredentials, credentials);
    }

    Mst.Client.Auth.RememberMe = rememberUser;

    MstTimer.WaitForSeconds(0.5f, () =>
    {
        // Listen to connection events
        Connection.AddConnectionListener(OnClientConnectedToServer);
        Connection.AddDisconnectionListener(OnClientDisconnectedFromServer, false);

        if (!Connection.IsConnected && !Connection.IsConnecting)
        {
            clientToMasterConnector.StartConnection();
        }
    });
}

Рассмотрим метод OnInitialize, который при запуске инициализирует все необходимые системы для работы с авторизацией.

/// <summary>
/// Let's find or create master server connection
/// </summary>
protected virtual void FindOrCreateMasterConnector()
{
    if (!clientToMasterConnector)
        clientToMasterConnector = FindObjectOfType<ClientToMasterConnector>();

    if (!clientToMasterConnector)
    {
        var connectorObject = new GameObject("--CLIENT_TO_MASTER_CONNECTOR");
        clientToMasterConnector = connectorObject.AddComponent<ClientToMasterConnector>();
    }
}

Для того, чтобы наша авторизация работала нам необходимо подключение к мастер серверу. В нашем случае в методе FindOrCreateMasterConnector мы просто пытаемся найти помощник соединения или, если мы его не нашли в сцене, создать его.

Далее в методе инициализации мы устанавливаем учетные данные по умолчанию. Это мы делаем исключительно для режима работы в редакторе, просто чтобы не вводить свои данные постоянно. При помощи встроенной системы событий мы отправляем эти данные тем, кто на них подписан. В нашем случае это два окна. Первое окно входа, а второе окно регистрации.

// If we want to use default credentials for signin or signup views
if (useDefaultCredentials && Mst.Runtime.IsEditor)
{
    var credentials = new MstProperties();
    credentials.Set(MstDictKeys.userName, defaultUsername);
    credentials.Set(MstDictKeys.userPassword, defaultPassword);
    credentials.Set(MstDictKeys.userEmail, defaultEmail);

    Mst.Events.Invoke(MstEventKeys.setSignInDefaultCredentials, credentials);
    Mst.Events.Invoke(MstEventKeys.setSignUpDefaultCredentials, credentials);
}

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

Следующее, что мы делаем это устанавливаем подключение к мастер серверу если оно еще не установлено, подписываемся на события подключения и отключения.

MstTimer.WaitForSeconds(0.5f, () =>
{
    // Listen to connection events
    Connection.AddConnectionListener(OnClientConnectedToServer);
    Connection.AddDisconnectionListener(OnClientDisconnectedFromServer, false);

    if (!Connection.IsConnected && !Connection.IsConnecting)
    {
        clientToMasterConnector.StartConnection();
    }
});

В обработчике события подключения к мастер серверу OnClientConnectedToServer мы проверяем является ли пользователь авторизованным или нет. Также проверяем имеет ли неавторизованный пользователь токен авторизации и, если токен найден, то авторизуем игрока с помощью данного токена. Если же токен не найден, открываем окно авторизации.

protected virtual void OnClientConnectedToServer()
{
    Mst.Events.Invoke(MstEventKeys.hideLoadingInfo);

    if (Mst.Client.Auth.IsSignedIn)
    {
        OnSignedInEvent?.Invoke();
    }
    else
    {
        if (Mst.Client.Auth.HasAuthToken())
        {
            MstTimer.WaitForSeconds(0.2f, () =>
            {
                SignInWithToken();
            });
        }
        else
        {
            Mst.Events.Invoke(MstEventKeys.showSignInView);
        }
    }
}

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

protected virtual void OnClientDisconnectedFromServer()
{
    Connection.RemoveConnectionListener(OnClientConnectedToServer);
    Connection.RemoveDisconnectionListener(OnClientDisconnectedFromServer);

    Mst.Events.Invoke(MstEventKeys.hideLoadingInfo);
    Mst.Events.Invoke(MstEventKeys.showOkDialogBox,
        new OkDialogBoxEventMessage("The connection to the server has been lost. "
        + "Please try again or contact to the developers of the game or your internet provider.",
        () =>
        {
            SignOut();
            OnInitialize();
        }));
}

Далее идут обработчики событий авторизации. Думаю там все понятно.

/// <summary>
/// Invokes when user signed in
/// </summary>
protected virtual void Auth_OnSignedInEvent()

/// <summary>
/// Invokes when user signed up
/// </summary>
protected virtual void Auth_OnSignedUpEvent()

/// <summary>
/// Invokes when user signed out
/// </summary>
protected virtual void Auth_OnSignedOutEvent()

/// <summary>
/// Invokes when user changed his password
/// </summary>
protected virtual void Auth_OnPasswordChangedEvent()

/// <summary>
/// Invokes when user has confirmed his email
/// </summary>
protected virtual void Auth_OnEmailConfirmedEvent()

Метод SignIn выполняет авторизацию и проверку подтверждения адреса электронной почты пользователя если она обязательна. Также, если была установлена галочка Mst.Client.Auth.RememberMe, данный метод запоминает токен авторизации пользователя, который понадобится для быстрого входа в систему.

Далее идут методы входа в режиме гостя, регистрации, сброса пароля и подтверждения адреса электронной почты. 

Протестируйте текущую демо сцену и понаблюдайте как работает система авторизации с применением методов, упомянутых выше. UI компоненты, находящиеся в сцене позволяют выполнять различные задачи необходимые для авторизации. Откройте каждый UI компонент и посмотрите их работу, чтобы ознакомиться с их работой.

Все вопросы, касаемые авторизации пользователей задавайте в моем дискорд канале, указанном в главном меню сайта.