使用ServiceStack的OAuth +自定义用户表所需的最低代码是什么?

时间:2013-06-02 19:00:04

标签: c# .net oauth servicestack

我正在尝试关注SocialBootstrapApi示例,并仅使用4个提供商(Facebook,Twitter,GoogleOpenId和YahooOpenId)为我的网络应用设置身份验证。我还想将用户的元数据(FacebookUserName等)存储在自定义架构中(用户表已预先存在)。

是否需要注册服务?我更愿意只使用他们的OAuth对用户进行身份验证,并立即将数据保存为新用户(而不是使用2步注册,然后验证进程)。

我已经尝试了以下代码,但是当我GET或POST到AuthService的URL时,我收到一个错误:

Handler for Request not found: 


Request.ApplicationPath: /
Request.CurrentExecutionFilePath: /api/auth/googleopenid
Request.FilePath: /api/auth/googleopenid
Request.HttpMethod: GET
...

AppHost.cs

public class AppHost : AppHostBase {
    public AppHost() : base("...", typeof(HelloService).Assembly) { }

    public override void Configure(Container container) {
        container.Register<ICacheClient>(new MemoryCacheClient());

        ConfigureAuth(container);
        ConfigureRoutes();

        ControllerBuilder.Current.SetControllerFactory(new FunqControllerFactory(container));
        ServiceStackController.CatchAllController = reqCtx => container.TryResolve<HomeController>();
    }

    void ConfigureAuth(Container container) {
        var appSettings = new AppSettings();

        Plugins.Add(new AuthFeature(
            () => new CustomUserSession(),
            new IAuthProvider[] {
                new TwitterAuthProvider(appSettings),
                new FacebookAuthProvider(appSettings),
                new GoogleOpenIdOAuthProvider(appSettings),
                new YahooOpenIdOAuthProvider(appSettings)
            }));
    }

    void ConfigureRoutes() {
        Routes
            .Add<Hello>("/hello")
            .Add<Hello>("/hello/{Name*}")
        ;
    }

    public static void Start() {
        new AppHost().Init();
    }
}

CustomUserSession.cs

public class CustomUserSession : AuthUserSession {
    public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo) {
        base.OnAuthenticated(authService, session, tokens, authInfo);

        var user = session.TranslateTo<User>();
        user.ID = long.Parse(session.UserAuthId);
        user.GravatarUrl64 = !session.Email.IsNullOrEmpty()
            ? CreateGravatarUrl(session.Email)
            : null;

        foreach (var authToken in session.ProviderOAuthAccess) {
            if (authToken.Provider == FacebookAuthProvider.Name) {
                user.FacebookName = authToken.DisplayName;
                user.FacebookFirstName = authToken.FirstName;
                user.FacebookLastName = authToken.LastName;
                user.FacebookEmail = authToken.Email;
            } else if (authToken.Provider == TwitterAuthProvider.Name) {
                user.TwitterName = authToken.DisplayName;
            } else if (authToken.Provider == GoogleOpenIdOAuthProvider.Name) {
                user.GoogleUserId = authToken.UserId;
                user.GoogleFullName = authToken.FullName;
                user.GoogleEmail = authToken.Email;
            } else if (authToken.Provider == YahooOpenIdOAuthProvider.Name) {
                user.YahooUserId = authToken.UserId;
                user.YahooFullName = authToken.FullName;
                user.YahooEmail = authToken.Email;
            }
        }

        authService.TryResolve<IDbConnectionFactory>().Run(db => db.Save(user));
    }

Web.config

<appSettings>
  <add key="oauth.facebook.Permissions" value="email,read_stream,offline_access" />
  <add key="oauth.facebook.AppId" value="..." />
  <add key="oauth.facebook.AppSecret" value="..." />
  <add key="oauth.facebook.RedirectUrl" value="http://localhost:3000" />
  <add key="oauth.facebook.CallbackUrl" value="http://localhost:3000/api/auth/facebook" />

  <add key="oauth.twitter.ConsumerKey" value="..." />
  <add key="oauth.twitter.ConsumerSecret" value="..." />
  <add key="oauth.twitter.RedirectUrl" value="http://localhost:3000" />
  <add key="oauth.twitter.CallbackUrl" value="http://localhost:3000/api/auth/twitter" />

  <add key="oauth.GoogleOpenId.RedirectUrl" value="http://localhost:3000" />
  <add key="oauth.GoogleOpenId.CallbackUrl" value="http://localhost:3000/api/auth/googleopenid" />

  <add key="oauth.YahooOpenId.RedirectUrl" value="http://localhost:3000" />
  <add key="oauth.YahooOpenId.CallbackUrl" value="http://localhost:3000/api/auth/yahooopenid" />
</appSettings>

1 个答案:

答案 0 :(得分:1)

想出来 - 我已经通过NuGet安装了ServiceStack,该软件包包含了它自己的AppHost实现。简而言之,上面的Configure()方法实际上并未被调用。

以下是相关的问题/答案:

Service Stack/MVC: "AppHostBase.Instance has already been set" error - but can't understand why/how to prevent