【问题标题】:ServiceStack Authentication with Existing Database使用现有数据库的 ServiceStack 身份验证
【发布时间】:2013-01-14 20:56:49
【问题描述】:

我一直在研究 ServiceStack,并试图了解如何在具有现有数据库的服务上使用 BasicAuthentication。我想生成一个公钥(用户名)和密钥(密码)并将其放入现有的用户记录中。然后,用户会将其与他们的请求一起传递给 ServiceStack 端点。

我需要在 ServiceStack 堆栈中实现什么才能使其正常工作?

我查看了 IUserAuthRepository 和 CredentialsAuthProvider 基类,看起来我应该只在现有数据库表之上实现 IUserAuthRepository。

我还试图弄清楚我应该实现的最低限度是什么才能使身份验证正常工作。我不会使用该服务来添加或更新用户对服务的访问权限,而是使用单独的 Web 应用程序。

非常感谢任何帮助和过去的经验。

【问题讨论】:

    标签: c# servicestack basic-authentication


    【解决方案1】:

    针对现有数据库进行身份验证的示例(在本例中通过 Umbraco/ASP.NET 成员资格系统)。 1) 创建您的 AuthProvider(请原谅冗长的代码,并注意您不必也重写 TryAuthenticate,这是为了检查用户是否是特定 Umbraco 应用程序别名的成员):

    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Web.Security;
    
    using ServiceStack.Configuration;
    using ServiceStack.Logging;
    using ServiceStack.ServiceInterface;
    using ServiceStack.ServiceInterface.Auth;
    using ServiceStack.WebHost.Endpoints;
    
    using umbraco.BusinessLogic;
    using umbraco.providers;
    
    public class UmbracoAuthProvider : CredentialsAuthProvider
    {
    
        public UmbracoAuthProvider(IResourceManager appSettings)
        {
            this.Provider = "umbraco";
        }
    
        private UmbracoAuthConfig AuthConfig
        {
            get
            {
                return EndpointHost.AppHost.TryResolve<UmbracoAuthConfig>();
            }
        }
    
        public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
        {
            ILog log = LogManager.GetLogger(this.GetType());
            var membershipProvider = (UsersMembershipProvider)Membership.Providers["UsersMembershipProvider"];
    
            if (membershipProvider == null)
            {
                log.Error("UmbracoAuthProvider.OnAuthenticated - NullReferenceException - UsersMembershipProvider");
                session.IsAuthenticated = false;
                return;
            }
    
            MembershipUser user = membershipProvider.GetUser(session.UserAuthName, false);
    
            if (user == null)
            {
                log.ErrorFormat(
                    "UmbracoAuthProvider.OnAuthenticated - GetMembershipUser failed - {0}", session.UserAuthName);
                session.IsAuthenticated = false;
                return;
            }
    
            if (user.ProviderUserKey == null)
            {
                log.ErrorFormat(
                    "UmbracoAuthProvider.OnAuthenticated - ProviderUserKey failed - {0}", session.UserAuthName);
                session.IsAuthenticated = false;
                return;
            }
    
            User umbracoUser = User.GetUser((int)user.ProviderUserKey);
    
            if (umbracoUser == null || umbracoUser.Disabled)
            {
                log.WarnFormat(
                    "UmbracoAuthProvider.OnAuthenticated - GetUmbracoUser failed - {0}", session.UserAuthName);
                session.IsAuthenticated = false;
                return;
            }
    
            session.UserAuthId = umbracoUser.Id.ToString(CultureInfo.InvariantCulture);
            session.Email = umbracoUser.Email;
            session.DisplayName = umbracoUser.Name;
            session.IsAuthenticated = true;
            session.Roles = new List<string>();
            if (umbracoUser.UserType.Name == "Administrators")
            {
                session.Roles.Add(RoleNames.Admin);
            }
    
            authService.SaveSession(session);
            base.OnAuthenticated(authService, session, tokens, authInfo);
        }
    
        public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
        {
            ILog log = LogManager.GetLogger(this.GetType());
            var membershipProvider = (UsersMembershipProvider)Membership.Providers["UsersMembershipProvider"];
    
            if (membershipProvider == null)
            {
                log.Error("UmbracoAuthProvider.TryAuthenticate - NullReferenceException - UsersMembershipProvider");
                return false;
            }
    
            if (!membershipProvider.ValidateUser(userName, password))
            {
                log.WarnFormat("UmbracoAuthProvider.TryAuthenticate - ValidateUser failed - {0}", userName);
                return false;
            }
    
            MembershipUser user = membershipProvider.GetUser(userName, false);
    
            if (user == null)
            {
                log.ErrorFormat("UmbracoAuthProvider.TryAuthenticate - GetMembershipUser failed - {0}", userName);
                return false;
            }
    
            if (user.ProviderUserKey == null)
            {
                log.ErrorFormat("UmbracoAuthProvider.TryAuthenticate - ProviderUserKey failed - {0}", userName);
                return false;
            }
    
            User umbracoUser = User.GetUser((int)user.ProviderUserKey);
    
            if (umbracoUser == null || umbracoUser.Disabled)
            {
                log.WarnFormat("UmbracoAuthProvider.TryAuthenticate - GetUmbracoUser failed - {0}", userName);
                return false;
            }
    
            if (umbracoUser.UserType.Name == "Administrators"
                || umbracoUser.GetApplications()
                              .Any(app => this.AuthConfig.AllowedApplicationAliases.Any(s => s == app.alias)))
            {
                return true;
            }
    
            log.WarnFormat("UmbracoAuthProvider.TryAuthenticate - AllowedApplicationAliases failed - {0}", userName);
    
            return false;
        }
    }
    
    public class UmbracoAuthConfig
    {
    
        public UmbracoAuthConfig(IResourceManager appSettings)
        {
            this.AllowedApplicationAliases = appSettings.GetList("UmbracoAuthConfig.AllowedApplicationAliases").ToList();
        }
    
        public List<string> AllowedApplicationAliases { get; private set; }
    
    }
    

    2) 通过通常的 AppHost 配置方法注册提供者:

        public override void Configure(Container container)
        {
            // .... some config code omitted....
    
            var appSettings = new AppSettings();
            AppConfig = new AppConfig(appSettings);
            container.Register(AppConfig);
    
            container.Register<ICacheClient>(new MemoryCacheClient());
    
            container.Register<ISessionFactory>(c => new SessionFactory(c.Resolve<ICacheClient>()));
    
            this.Plugins.Add(
                new AuthFeature(
                    // using a custom AuthUserSession here as other checks performed here, e.g. validating Google Apps domain if oAuth enabled/plugged in.
                    () => new CustomAuthSession(), 
                    new IAuthProvider[] { new UmbracoAuthProvider(appSettings) 
                                        }) {
                                              HtmlRedirect = "/api/login" 
                                           });
    
    }
    

    3) 现在可以针对现有的 Umbraco 数据库@yourapidomain/auth/umbraco 进行身份验证,使用 Umbraco 来管理用户/对 API 的访问。无需实现额外的用户密钥/秘密或 BasicAuthentication,除非您真的想......

    【讨论】:

    • 注意:这是使用托管在同一站点中的 ServiceStack 3.9.43 和 Umbraco 4.7.2,在 Umbraco 内容页面中呈现来自 ServiceStack 的 Razor'd Html。由于最近对 ServiceStack(特别是升级到 Razor 2)和 Umbraco API (v6) 的更改,这可能需要进行一些调整才能使用较新的版本(甚至在单独的进程中托管)。当我们解决这个问题时会发布更新......
    【解决方案2】:

    我刚开始使用 ServiceStack,我需要完全相同的东西 - 今天我设法让它工作。

    通过基本身份验证登录用户的最低限度如下:

    using ServiceStack.ServiceInterface;
    using ServiceStack.ServiceInterface.Auth;
    
    public class CustomBasicAuthProvider : BasicAuthProvider
    {
        public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
        {
            // here, you can get the user data from your database instead
            if (userName == "MyUser" && password == "123")
            {
                return true;
            }
    
            return false;
        }
    }
    

    ...并将其注册到AppHost:

    Plugins.Add(new AuthFeature(() => new CustomUserSession(),
        new IAuthProvider[] {
            new CustomBasicAuthProvider()
        }) { HtmlRedirect = null });
    

    就是这样!


    另一种可能的解决方案是使用默认的BasicAuthProvider 并提供自己的IUserAuthRepository 实现。

    如果你有兴趣,我也可以给你看一个例子。


    编辑:

    这是最低限度的IUserAuthRepository - 只需从InMemoryAuthRepository 继承并覆盖TryAuthenticate

    using ServiceStack.ServiceInterface.Auth;
    
    public class CustomAuthRepository : InMemoryAuthRepository
    {
        public override bool TryAuthenticate(string userName, string password, out UserAuth userAuth)
        {
            userAuth = null;
    
            if (userName == "MyUser" && password == "123")
            {
                userAuth = new UserAuth();
                return true;
            }
    
            return false;
        }
    }
    

    ...并将其注册到AppHost:

    container.Register<IUserAuthRepository>(r => new CustomAuthRepository());
    

    当然,您还需要注册默认AuthProviders 之一(基本、凭据等)。

    【讨论】:

    • IUserAuthRepository 的示例是值得的。同时我将尝试让您的示例与 CredentialsAuthProvider 一起使用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-09-23
    • 2016-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-25
    • 1970-01-01
    相关资源
    最近更新 更多