gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 21:21:40 25 4
gpt4 key购买 nike

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

最佳答案

鉴于标准成员提供程序 API 是基于非通用接口(interface)的,因此没有替代实现。

但是,在实践中,整个成员(member) API 增加的值(value)很少,而且推出您自己的解决方案相当容易。

为了帮助您入门,这里提供了一些我通常使用的帮助器类。

首先是一些处理cookies和Forms认证的代码:

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

其次,一些根据数据存储验证用户的代码。您需要为此接口(interface)提供您自己的实现(和/或使其适应您的需要)。

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 类使用):

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 实现相关联。这只是为您提供思路的快速摘录:

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 类:

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
}

如果你不需要的话,你可以去掉这些位来检查访问者的主机地址。

即使它本身不是成员(member)提供者,我也希望这能有所帮助 ;-)

关于c# - ASP.NET:在哪里可以找到快速的自定义成员资格提供程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2614965/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com