ASP.NET:我在哪里可以找到一个快速的定义成员资格提供 [英] ASP.NET: Where can I find a fast custom membership provider

查看:86
本文介绍了ASP.NET:我在哪里可以找到一个快速的定义成员资格提供的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在那里,有人已经在网上创建的任何自定义asp.net成员资格提供。我想用一个自定义供应商,因为他们的角色提供非常缓慢,我想用整数而不是GUID的用户ID

is there any custom asp.net membership providers that someone has already created online. I want to use a custom provider because their role provider is very sluggish and I would like to use integers instead of guids for user IDs

推荐答案

有可能是标准的成员提供的API没有替代实现,因为它是基于非通用接口。

There can be no alternative implementations of the standard membership provider API, given that it is based on non-generic interfaces.

然而,在实践中,全体成员API增加了很少的价值,这是很容易推出自己的解决方案。

However, in practice the whole membership API adds very little value and it is fairly easy to roll your own solution.

为了帮助你在这里开始有一些,我通常使用的辅助类的。

To help you get started here are a few of the helper classes that I typically use.

首先,一些code处理Cookie和Forms身份验证:

First, some code to deal with cookies and Forms authentication:

public interface ISecurityPersistenceProvider
{
    void SetAuthCookie( int version, string name, DateTime expireDate, bool persistent, string cookieData );
    HttpCookie GetAuthCookie();
    string GetAuthCookieValue( out string name );
    void RemoveAuthCookie();
}

public class FormsPersistenceProvider : ISecurityPersistenceProvider
{
    public void SetAuthCookie( int version, string name, DateTime expireDate, bool persistent, string cookieData )
    {
        var ticket = new FormsAuthenticationTicket( version, name, DateTime.Now, expireDate, persistent, cookieData );
        string secureTicket = FormsAuthentication.Encrypt( ticket );
        var cookie = new HttpCookie( FormsAuthentication.FormsCookieName, secureTicket );
        cookie.Expires = ticket.Expiration;
        HttpContext.Current.Response.Cookies.Add( cookie );
    }

    public HttpCookie GetAuthCookie()
    {
        HttpCookie cookie = HttpContext.Current.Request.Cookies[ FormsAuthentication.FormsCookieName ];
        return cookie;
    }

    public string GetAuthCookieValue( out string name )
    {
        HttpCookie cookie = GetAuthCookie();
        FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt( cookie.Value );
        name = ticket.Name;
        return ticket.UserData;
    }

    public void RemoveAuthCookie()
    {
        FormsAuthentication.SignOut();
    }
}

其次,一些code,以验证用户对数据存储。您需要提供自己的实现此接口(和/或它适应您的需求)。

Second, some code to validate users against a data store. You'll need to provide your own implementation for this interface (and/or adapt it to your needs).

public interface ISecurityUserProvider<T> where T : class
{
    T AuthenticateUser( string customer, string userName, string passwordHash );
    T GetUser( string customer, string userName );
    string[] GetRoles( T user );
}

三,一类让我们回到调用者的附加信息(这将由以下SecurityManager类中使用):

Third, a class to let us return additional information to callers (this will be used by the SecurityManager class below):

public class AuthenticationResult
{
    #region Fields/Properties
    public bool Success { get; internal set; }
    public string Message { get; internal set; }
    public IDictionary<string,string> Errors { get; internal set; }
    #endregion

    #region Constructors
    public AuthenticationResult( bool success, string message ) : this( success, message, null )
    {
    }
    public AuthenticationResult( bool success, string message, IDictionary<string, string> errors )
    {
        Success = success;
        Message = message;
        Errors = errors ?? new Dictionary<string, string>();
    }
    #endregion
}

我还使用一个自定义的主类,允许我去一个自定义对象的基本的IPrincipal实现相关联。这仅仅是一个快速提取物,给你的理念是:

I'm also using a custom principal class that allows me to associate a custom object with the basic IPrincipal implementation. This is just a quick extract to give you the idea:

public class CodeworksPrincipal<TUserData> : IPrincipal where TUserData : class
{
    private string name;
    private string[] roles;
    private string allRoles;
    private TUserData userData;

    public CodeworksPrincipal( string name, string[] roles, TUserData userData )
    {
        // init fields, etc.
    }
}

最后,SecurityManager类与散装的逻辑:

And finally, the SecurityManager class with the bulk of the logic:

public class SecurityManager<T,TPersistenceProvider,TUserProvider> 
    where T : class
    where TPersistenceProvider : ISecurityPersistenceProvider
    where TUserProvider : ISecurityUserProvider<T>
{
    private readonly ISecurityPersistenceProvider persistenceProvider;
    private readonly ISecurityUserProvider<T> userProvider;
    // NOTE this constant is used to validate the validity of the cookie (see below)
    private const int CookieParameterCount = 3;

    public SecurityManager( ISecurityPersistenceProvider persistenceProvider, ISecurityUserProvider<T> userProvider )
    {
         this.persistenceProvider = persistenceProvider;
         this.userProvider = userProvider;
    }

    #region Properties
    protected ISecurityPersistenceProvider PersistenceProvider
    {
        get { return persistenceProvider; }
    }
    protected ISecurityUserProvider<T> UserProvider
    {
        get { return userProvider; }
    }
    public IIdentity CurrentIdentity
    {
        get { return Thread.CurrentPrincipal.Identity; }
    }
    public bool IsAuthenticated
    {
        get
        {
            IPrincipal principal = Thread.CurrentPrincipal;
            return principal != null && principal.Identity != null && principal.Identity.IsAuthenticated;
        }
    }
    public bool IsInRole( string roleName )
    {
        IPrincipal principal = Thread.CurrentPrincipal;
        return IsAuthenticated && principal.IsInRole( roleName );
    }
    public string UserName
    {
        get { return IsAuthenticated ? CurrentIdentity.Name : ""; }
    }
    #endregion

    #region Authentication
    public AuthenticationResult Authenticate( string userName, string password, bool persistent, string visitorAddress )
    {
        return Authenticate( null, userName, password, persistent, visitorAddress );
    }
    public AuthenticationResult Authenticate( string customer, string userName, string password, bool persistent, string visitorAddress )
    {
        AuthenticationResult result = ValidateInput( userName, password );
        if( ! result.Success )
            return result;
        string passwordHash = GetCryptographicHash( password );
        T user = userProvider.AuthenticateUser( customer, userName, passwordHash );
        if( user == null )
            return new AuthenticationResult( false, "Unable to login using the specified credentials.", null );
        if( ! IsAuthorizedVisitor( user, visitorAddress ) )
            return new AuthenticationResult( false, "Credentials do not allow login from your current IP address.", null );
        CurrentPrincipal = new CodeworksPrincipal<T>( userName, userProvider.GetRoles( user ), user );
        // remember to change CookieParameterCount if you change parameter count here
        string cookieData = String.Format( "{0}|{1}|{2}", CurrentIdentity.Name, customer, CurrentPrincipal.AllRoles );
        persistenceProvider.SetAuthCookie( 1, userName, DateTime.Now.AddMonths( 1 ), persistent, cookieData );
        // TODO create an audit log entry for the current request
        return new AuthenticationResult( true, null, null );
    }
    private AuthenticationResult ValidateInput( string login, string password )
    {
        var result = new AuthenticationResult( true, "Invalid or missing credentials." );
        if( String.IsNullOrEmpty( login ) )
        {
            result.Success = false;
            result.Errors.Add( "login", "You must specify an alias or email address." );
        }
        if( String.IsNullOrEmpty( password ) )
        {
            result.Success = false;
            result.Errors.Add( "password", "You must specify a password." );
        }
        // TODO add message to inform users of other requirements.
        return result;            
    }
    #endregion

    #region Cookie Authentication
    public void CookieAuthenticate( string visitorAddress )
    {
        HttpCookie cookie = persistenceProvider.GetAuthCookie();
        if( cookie != null )
        {
            string userName;
            string userData = persistenceProvider.GetAuthCookieValue( out userName );
            string[] cookieData = userData.Split( '|' );
            // extract data from cookie
            bool isValid = cookieData.Length == CookieParameterCount && 
                           ! string.IsNullOrEmpty( cookieData[ 0 ] ) &&
                           cookieData[ 0 ] == userName &&
                           IsAuthorizedVisitor( cookieData[ 1 ], cookieData[ 0 ], visitorAddress );
            if( isValid )
            {
                string customer = cookieData[ 1 ];
                string[] roles = cookieData[ 2 ].Split( ',' );
                T user = userProvider.GetUser( customer, userName );

                CurrentPrincipal = new CodeworksPrincipal<T>( userName, roles, user );
            }
        }
    }
    #endregion

    #region Logout
    public void Logout()
    {
        // logout the current user
        if( HttpContext.Current.Request.IsAuthenticated || CurrentPrincipal != null )
        {
            long address = GetAddressFromString( HttpContext.Request.UserHostAddress );
            // TODO add audit log entry
            // sign out current user
            persistenceProvider.RemoveAuthCookie();
            CurrentPrincipal = null;
        }
    }
    #endregion

    #region VisitorAddress Checks
    public long GetAddressFromString( string address )
    {
        IPAddress ipAddress;
        if( IPAddress.TryParse( address, out ipAddress ) )
        {
            byte[] segments = ipAddress.GetAddressBytes();
            long result = 0;
            for( int i = 0; i < segments.Length; i++ )
            {
                result += segments[ i ] << (i * 8);
            }
            return result;
        }
        return long.MaxValue;
    }

    public bool IsAuthorizedVisitor( string customer, string userName, string visitorAddress )
    {
        return IsAuthorizedVisitor( customer, userName, GetAddressFromString( visitorAddress ) );
    }

    public bool IsAuthorizedVisitor( string customer, string userName, long visitorAddress )
    {
        T user = userProvider.GetUser( customer, userName );
        return IsAuthorizedVisitor( user, visitorAddress );
    }

    public bool IsAuthorizedVisitor( T user, string visitorAddress )
    {
        return IsAuthorizedVisitor( user, GetAddressFromString( visitorAddress ) );
    }

    public bool IsAuthorizedVisitor( T user, long visitorAddress )
    {
        if( user == null || visitorAddress == 0 )
            return false;
        if( user.Hosts.Count == 0 )
            return true;
        foreach( Host host in user.Hosts )
        {
            if( IsAuthorizedVisitor( host.HostAddress, host.HostMask, visitorAddress ) )
                return true;
        }
        return true;
    }

    public bool IsAuthorizedVisitor( long allowedAddress, long allowedMask, long visitorAddress )
    {
        long requireMask = allowedAddress & allowedMask;
        return (visitorAddress & requireMask) == requireMask;
    }
    #endregion

    #region Cryptographic Helpers
    public static string GetCryptographicHash( string password )
    {
        SHA256 hash = SHA256.Create();
        byte[] input = Encoding.UTF8.GetBytes( password );
        byte[] output = hash.ComputeHash( input );
        return Convert.ToBase64String( output );
    }
    #endregion
}

您可以剥离出位,检查访客主机地址,如果你不需要它。

You can strip out the bits to check the visitors host address if you don't need it.

我希望,如果它不是一个成员提供程序本身这有助于均匀; - )

I hope this helps even if it isn't a membership provider per se ;-)

这篇关于ASP.NET:我在哪里可以找到一个快速的定义成员资格提供的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆