Вопрос

I'm creating a SPA using ServiceStack and AngularJs. When a user logs in I set some variables in the OnAuthenticated method:

    public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
    {
        var sessionUser = session.TranslateTo<AppUserSession>();
        var user = _userRepo.LoadUser(session.UserAuthName);

        var userSettings = ConfigurationSettings.Load(user);

        var customers = _customerRepo.ToList();
        sessionUser.UserName = user.UserName;
        sessionUser.DisplayName = user.DisplayName;
        sessionUser.CustomerCount = customers.Count;
        sessionUser.CustomerRecordId = customers.First().RecordID;
        sessionUser.RefreshRate = userSettings.RefreshRate;

        authService.SaveSession(sessionUser, SessionExpiry);
    }

So my question is, how can I then access this information in Javascript? Do I need to create a Service which exposes them or is it returned in a HTTP header?

Это было полезно?

Решение

Do I need to create a Service which exposes them or is it returned in a HTTP header?

The custom parameters you add to the session are not exposed in any way by ServiceStack, by default.

Expose from Login Result:

You can return this information in the response from your login, as part of a successful response.

At the moment the default response from ServiceStack's CredentialsAuthProvider is:

return new AuthResponse {
    UserName = userName,
    SessionId = session.Id,
    ReferrerUrl = referrerUrl
};

You can customise this in your custom authentication provider, by overriding the Authenticate method.

Most of the code in this method is copied from the original CredentialsAuthProvider authenticate method (here) and then adapted to use your custom session type (AppUserSession) and populate a custom response.

public override object Authenticate(IServiceBase authService, IAuthSession session, Auth request)
{
    var userName = request.UserName;
    var password = request.Password;

    if (!LoginMatchesSession(session, userName))
    {
        authService.RemoveSession();
        session = authService.GetSession();
    }

    if (TryAuthenticate(authService, userName, password))
    {
        session.IsAuthenticated = true;

        if (session.UserAuthName == null)
        {
            session.UserAuthName = userName;
        }

        OnAuthenticated(authService, session, null, null);

        var sessionUser = authService.GetSession() as AppUserSession;

        // Return your Authentication Response DTO here
        return new {
            UserName = userName,
            SessionId = session.Id,
            DisplayName = sessionUser.DisplayName,
            CustomerCount = sessionUser.CustomerCount,
            ...
        };
    }

    throw HttpError.Unauthorized("Invalid UserName or Password");
}

Expose using a Service:

You could expose them by writing a custom service that would return this additional information, but that then requires another request after successfully logging in, and that would add more delay for the user, and data overhead.

[Route("/SessionInfo", "GET")]
public class GetSessionInfoRequest : IReturn<SessionInfo>

public class SessionInfo
{
    public string Username { get; set; }
    public string DisplayName { get; set; }
    public int CustomerCount { get; set; }
    ...
}

[Authenticate]
public class SessionInfoService : Service
{
    public SessionInfo Get(GetSessionInfoRequest request)
    {
        var sessionUser = SessionAs<AppUserSession>();
        return new SessionInfo {
            UserName = sessionUser.UserName,
            DisplayName = sessionUser.DisplayName,
            CustomerCount = sessionUser.CustomerCount,
            ...
        };
    }
}

The only real benefit of exposing as a service, is you would be able to call it later, and get fresher values of the data (if it has changed) without having to re-authenticate.

Hope that helps.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top