MonoTouch如何在每个ServiceStack请求中提供cookie?

时间:2013-03-30 20:11:45

标签: authentication cookies xamarin.ios servicestack xamarin

我花了几天时间试图掌握ServiceStack,看起来很棒。唯一的问题是认证,这似乎是很多摩擦,努力工作和眼泪。

我希望MonoTouch注册用户,针对ServiceStack进行身份验证/针对OAuth进行身份验证,并且通常在进行身份验证时最大限度地减少对数据库的调用。

到目前为止,我已经得到了这个:

       var client = new JsonServiceClient(newbaseUri);

// register a new user:

        var registration  = new Registration {
            FirstName = "john"
            UserName = "user" ,
            Password = "pass",
            Email =   "john@john.com",              
        };

        var registerResponse = client.Send<RegistrationResponse>(registration);

       --------------------------------

// user registered...later on I authenticate:

        var authResponse = client.Send<AuthResponse>(new Auth {
            UserName = "user",
            Password = "pass",
            RememberMe = true
        });

        var authResponse = clientlogin.Send<AuthResponse>(auth);

        --------------------------------    

// somehow I need to store 'authresponse' for later calls, not sure how without a browser 
// tried manually setting the cookies and credentials parameters later but no joy
// but now I need to call a secured ([Authenticate] decorated) service method:

        var client = new JsonServiceClient(newbaseUri);
        var response = client.Send<HelloResponse>(new Hello { Name = "World!" });           
        return response.Result;

-----------------------------------------

// heres the configuration

        var appSettings = new AppSettings();

        //Default route: /auth/{provider}
        Plugins.Add(new AuthFeature(() => new CustomUserSession(),
            new IAuthProvider[] {
                new CredentialsAuthProvider(appSettings),  // never seems to get called
                //new FacebookAuthProvider(appSettings),    // not sure how to get this to work on monotouch
                //new TwitterAuthProvider(appSettings),    // same issue as facebook
                new BasicAuthProvider(appSettings)    // works but what about caching/tokens/cookies?
            }));

        //Default route: /register
        Plugins.Add(new RegistrationFeature());    // how do i send extra params to this as created in mongodb collection


        var mongoClient = new MongoClient("mongodb://localhost");
        var server = mongoClient.GetServer();
        var db = server.GetDatabase("users");

        container.Register<ICacheClient>(new MemoryCacheClient());
        container.Register<IUserAuthRepository>(new MongoDBAuthRepository(db, true));

我的问题是:

1)如何启用额外字段以及注册(因为mongodb [Servicestack.Authentication.Mongodb]有很多空字段,例如生日,第一行,城市,时区等),这些字段不存在于ServiceStack.Common.ServiceClient.Web.Registration对象?

2)如何将'authresponse'中发送的cookie(甚至可能是令牌系统)传输到后续调用,以便允许ServiceStack与会话进行匹配以进行持续身份验证,而不是更多正在进行的数据库调用问题是'基本身份验证'方法(即在服务器端没有调用CredentialsAuthProvider)?

请帮助......我已经阅读了文档,运行测试,检查了社交引导程序,现在我正在认真地失去了几天的时间,并且考虑将SS与简单的成员集成,甚至完全抛弃ServiceStack用于旧的skool soap / wcf通过它的外观更容易实现:(

1 个答案:

答案 0 :(得分:3)

1)如果您想使用注册插件,我不认为您可以添加其他字段,因为已经定义了注册请求/类。您可以创建自己的注册服务并调用RegistrationService / Plugin。此外,this post可能会有所帮助。

[Route("/myregistration")]
public class MyRegistration : Registration //Add Additional fields for registration
{
    public DateTime? BirthDate { get; set;  }
    public string Gender { get; set; } 
}

public class MyRegisterService : Service
{
    public IUserAuthRepository UserAuthRepo { get; set; }
    public object Post(MyRegistration request)
    {
        using (var registrationService = base.ResolveService<RegistrationService>())
        {
            //handle the registration 
            var response = registrationService.Post(request.TranslateTo<Registration>());
        }

        //save the additional data
        var userAuth = request.TranslateTo<UserAuth>();
        UserAuthRepo.SaveUserAuth(userAuth);

        //can make your own response or grab response from RegistrationService above    
        return new MyRegistrationResponse();
    }
}

2)您可以验证您的JsonServiceClient并重复使用它来发出多个请求。

var client = new JsonServiceClient(newbaseUri);
var authResponse = client.Send<AuthResponse>(new Auth {
    UserName = "user",
    Password = "pass",
    RememberMe = true
}); //if successful your 'client' will have a populated CookieContainer with 'ss-id' and 'ss-pid' values

//reusing 'client' (after successful authentication) to make a request
//to a service requiring authentication
var response = client.Send<HelloResponse>(new Hello { Name = "World!" });

如果重复使用您的客户&#39;不是您可以尝试存储ss-id的选项。我不太了解MonoTouch以及它如何存储浏览器会话&#39;所以我不确定你会怎么做到这一点。在验证并存储ss-id之后,您可以使用请求过滤器将其添加到客户端

//Get ss-id value
foreach(Cookie cookie in previousAuthenticatedClient.GetCookies(new Uri(newbaseUri)))
{
    if (cookie.Name == "ss-id") 
    {
        //store ss-id 
    }
}

var newClient = new JsonServiceClient(newbaseUri)
{
    LocalHttpWebRequestFilter = (req) =>
        {
            req.CookieContainer.Add(new Uri("http://localhost:56006"), new System.Net.Cookie("ss-id", ssId));
        }
};