ASP.NET:我在哪里可以找到快速自定义成员资格提供程序

是否有人已经在线创建的自定义asp.net会员提供商。 我想使用自定义提供程序,因为他们的角色提供程序非常缓慢,我想使用整数而不是guids用于用户ID

标准成员资格提供程序API没有替代实现,因为它基于非通用接口。

但是,在实践中,整个成员资格API增加了很少的价值,并且很容易推出自己的解决方案。

为了帮助您入门,我通常使用了一些辅助类。

首先,一些代码来处理cookie和Forms身份validation:

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(); } } 

其次,一些代码用于根据数据存储validation用户。 您需要为此界面提供自己的实现(和/或根据您的需要进行调整)。

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

第三,让我们向调用者返回附加信息的类(这将由下面的SecurityManager类使用):

 public class AuthenticationResult { #region Fields/Properties public bool Success { get; internal set; } public string Message { get; internal set; } public IDictionary Errors { get; internal set; } #endregion #region Constructors public AuthenticationResult( bool success, string message ) : this( success, message, null ) { } public AuthenticationResult( bool success, string message, IDictionary errors ) { Success = success; Message = message; Errors = errors ?? new Dictionary(); } #endregion } 

我还使用了一个自定义主体类,它允许我将自定义对象与基本的IPrincipal实现相关联。 这只是一个快速提取,为您提供的想法:

 public class CodeworksPrincipal : 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类具有大量逻辑:

 public class SecurityManager where T : class where TPersistenceProvider : ISecurityPersistenceProvider where TUserProvider : ISecurityUserProvider { private readonly ISecurityPersistenceProvider persistenceProvider; private readonly ISecurityUserProvider 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 userProvider ) { this.persistenceProvider = persistenceProvider; this.userProvider = userProvider; } #region Properties protected ISecurityPersistenceProvider PersistenceProvider { get { return persistenceProvider; } } protected ISecurityUserProvider 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( 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( 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 } 

如果您不需要,可以删除位以检查访问者主机地址。

我希望这有助于即使它本身不是会员提供者;-)