Setting ServiceStack Cookie Domain in Web.Config C

2019-02-27 05:44发布

问题:

As per ServiceStack - Authentication for domain and subdomains, I set the cookie domain in the httpCookies section and it in fact works - it sets the domain of the cookie properly.

But what I noticed is, once I add this line to the config, a new session id is generated on every request, regardless if the user has already been authenticated.

My code is bare bones and simple.

My app host code:

public override void Configure(Funq.Container container)
{
        Plugins.Add(new AuthFeature(() => new CustomUserSession(),
            new IAuthProvider[] {        
                    new CustomCredentialsProvider(), 
                }));

        container.Register<IRedisClientsManager>(c => new PooledRedisClientManager("10.211.55.2:6379"));
        container.Register<ICacheClient>(c => c.Resolve<IRedisClientsManager>().GetCacheClient());

        var userRep = new InMemoryAuthRepository();
        container.Register<IUserAuthRepository>(userRep);
}

My custom credentials provider:

public class CustomCredentialsProvider : CredentialsAuthProvider
{
    public override bool TryAuthenticate(ServiceStack.IServiceBase authService, string userName, string password)
    {
        return true;
    }

    public override void OnAuthenticated(ServiceStack.IServiceBase authService, IAuthSession session, IAuthTokens tokens, Dictionary<string, string> authInfo)
    {
        session.UserAuthName = "test user";
        session.UserName = "test user";

        authService.SaveSession(session);
    } 
}

My default page:

public partial class _Default : WebForms.App_Start.PageBase
{
    protected void Page_Load(object sender, EventArgs e)
    {
        try
        {
            //get session information in every way possible
            var session = this.UserSession;

            var sessionKey = SessionFeature.GetSessionKey();

            var session2 = SessionFeature.GetOrCreateSession<CustomUserSession>(this.Cache);

            var session3 = this.Cache.Get<CustomUserSession>(sessionKey);        

        }

sessionKey, above, will be issued and will stay the same on every request (which is expected). Adding:

<system.web>
  <httpCookies domain="localhost"/>

causes sessionKey to be different every request; almost like the cookie is immediately expiring. Changing the domain to something like 'test.com' or '.test.com' doesn't seem to make a difference. I added 127.0.0.1 localhost and 127.0.0.1 test.com to my windows hosts file for good measure.

Again, commenting out the httpCookies line and the session id stays the same, even after authenticating. Adding the above line causes session to change on every request, regardless of authenticating or not.

Cookies are being set, and they are set with the new session id on every request.

What might I be doing wrong and where would I override this behavior? Any help is appreciated.

回答1:

This doesn't look like a ServiceStack issue, but rather a problem with your browser not accepting the returned cookie because your test domains are invalid choices.

localhost is not a valid cookie domain:

You shouldn't be setting the domain to localhost, as this is not valid cookie domain. For a cookie domain to be considered valid it must have a . in it. So when working with localhost the domain value must be null.

IP addresses are not valid cookie domains:

You cannot use an IP address as a cookie domain. So setting 127.0.0.1 can be considered invalid by the browser.

Hosts file:

You said you setup test.com to point to 127.0.0.1 in your hosts file. Given that your ServiceStack service is listening on the loopback address then the domain test.com should work for the service, but you would have to reflect that in the configuration, i.e.

<system.web>
    <httpCookies domain="test.com"/>

You could alternatively configure this directly in your AppHost Configure method:

public override void Configure(Container container)
{
    Config = new HostConfig {
        RestrictAllCookiesToDomain = "test.com",
    };
}

If ServiceStack is correctly setting the cookie, which you say it is, then the problem has to be with the cookie not being accepted by the browser. You can confirm this be checking the cookies the browser is sending with the request. If you are not seeing a cookie sent back with your next request, the browser didn't accept them. You have to ensure that you are making requests from http://test.com and not from localhost or 127.0.0.1.



回答2:

Thanks Scott, this was the ticket - winds up I found similar info when expanding my search past ServiceStack.

The only other trick was to get Visual Studio to use a custom domain instead of the standard 'localhost' when debugging locally (which explains why the session was being regenerated on each request).

There are other threads that show how to do this but no examples outside of the standard port 80. So here we go:

  • add a line to the hosts file: 127.0.0.1 my.test.com
  • open IISExpress config (C:\Users\someuser\Documents\IISExpress\config\applicationHost.config), find the section for your project and alter it similar to this: <binding protocol="http" bindingInformation="*:1412:my.test.com" />
  • go to the project properties: set Override application url to: http://my.test.com:1412 and set start url to: http://my.test.com:1412/default (or whatever your start page or service is).

I would post a screenshot but I don't have a reputation yet :)

Running the project should now use the custom domain when debugging locally in Visual Studio using the custom domain of your choice.