Servicestack user session not working

2019-07-26 05:24发布

问题:

I have an API written in ServiceStack and I am attempting to build in authentication for clients. At the moment this API will only be accessed by Android clients (Xamarin / C#). The API itself is running on a Debian server with Apache / mod_mono

After reading up on Github, I am still not 100% sure how to put this together in such a way that... once the client has provided valid credentials (For testing, basic HTTP authentication) the user gets a session and the credentials are not checked again on subsequent requests from the same session.

AppHost Class:

{
public class AppHost
    : AppHostBase
{       
    public AppHost() //Tell ServiceStack the name and where to find your web services
        : base("Service Call Service", typeof(ServiceCallsService).Assembly) { }

    public override void Configure(Funq.Container container)
    {
        //Set JSON web services to return idiomatic JSON camelCase properties
        ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;

        // Session storage
        container.Register<ICacheClient>(new MemoryCacheClient());

        // auth feature and session feature
        Plugins.Add(new AuthFeature(
            () => new AuthUserSession(),
            new[] { new userAuth() }
        ) { HtmlRedirect = null } );
    }

    public class userAuth : BasicAuthProvider
    {
        public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
        {
            peruseAuth peruseAuthHandler= new peruseAuth();
            errorLogging MyErrorHandler = new errorLogging() ; 
            if (peruseAuthHandler.ValidateUser(authService, userName, password))
            {
                try
                {
                    var session = (AuthUserSession)authService.GetSession(false);
                    session.UserAuthId = userName;
                    session.IsAuthenticated = true;
                    return true;
                }
                catch(Exception ex) 
                {
                   MyErrorHandler.LogError(ex, this) ;
                    return false ; 
                }
            }
            else
            {
                Console.Write("False");
                return false;
            }
        }
    }

The JsonServiceClient: (Just the "login" event)

        btnLogin.Click += (sender, e) =>
            {
                // Set credentials from EditText elements in Main.axml
                client.SetCredentials(txtUser.Text, txtPass.Text);

                // Force the JsonServiceClient to always use the auth header
                client.AlwaysSendBasicAuthHeader = true;

            };

I've been doing a bit of logging, and it seems that every time the client performs an action their username/password is being checked against the database. Is there something wrong here, or is this the expected result?

回答1:

For Basic Auth where the credentials are sent on each request it's expected.

In order for the ServiceClient to retain the Session cookies that have been authenticated you should set the RememberMe flag when you authenticate, e.g using CredentialsAuthProvider:

var client = new JsonServiceClient(BaseUrl);
var authResponse = client.Send(new Authenticate {
    provider = "credentials", 
    UserName = "user",
    Password = "p@55word",
    RememberMe = true,
});

Behind the scenes this attaches the user session to the ss-pid cookie (permanent session cookie), which the client retains and resends on subsequent requests from that ServiceClient instance.