[英]Review my ASP.NET Authentication code
我在ASP.NET中遇到了一些身份驗證問題。 我沒有在.NET中使用大多數內置身份驗證。
我收到了一些用戶使用Internet Explorer(任何版本 - 也可能會影響其他瀏覽器)的一些抱怨登錄過程繼續進行,但是當重定向時,他們沒有經過身份驗證並被退回到登錄頁面(如果登錄需要進行身份驗證檢查的頁面,如果不重定向回登錄頁面)。 這可能是一個cookie問題嗎?
我是否需要檢查用戶是否啟用了cookie?
如果您有自定義成員表並且不想使用ASP.NET登錄控件,那么構建身份驗證的最佳方法是什么?
這是我目前的代碼:
using System;
using System.Linq;
using MyCompany;
using System.Web;
using System.Web.Security;
using MyCompany.DAL;
using MyCompany.Globalization;
using MyCompany.DAL.Logs;
using MyCompany.Logging;
namespace MyCompany
{
public class Auth
{
public class AuthException : Exception
{
public int StatusCode = 0;
public AuthException(string message, int statusCode) : base(message) { StatusCode = statusCode; }
}
public class EmptyEmailException : AuthException
{
public EmptyEmailException() : base(Language.RES_ERROR_LOGIN_CLIENT_EMPTY_EMAIL, 6) { }
}
public class EmptyPasswordException : AuthException
{
public EmptyPasswordException() : base(Language.RES_ERROR_LOGIN_CLIENT_EMPTY_PASSWORD, 7) { }
}
public class WrongEmailException : AuthException
{
public WrongEmailException() : base(Language.RES_ERROR_LOGIN_CLIENT_WRONG_EMAIL, 2) { }
}
public class WrongPasswordException : AuthException
{
public WrongPasswordException() : base(Language.RES_ERROR_LOGIN_CLIENT_WRONG_PASSWORD, 3) { }
}
public class InactiveAccountException : AuthException
{
public InactiveAccountException() : base(Language.RES_ERROR_LOGIN_CLIENT_INACTIVE_ACCOUNT, 5) { }
}
public class EmailNotValidatedException : AuthException
{
public EmailNotValidatedException() : base(Language.RES_ERROR_LOGIN_CLIENT_EMAIL_NOT_VALIDATED, 4) { }
}
private readonly string CLIENT_KEY = "9A751E0D-816F-4A92-9185-559D38661F77";
private readonly string CLIENT_USER_KEY = "0CE2F700-1375-4B0F-8400-06A01CED2658";
public Client Client
{
get
{
if(!IsAuthenticated) return null;
if(HttpContext.Current.Items[CLIENT_KEY]==null)
{
HttpContext.Current.Items[CLIENT_KEY] = ClientMethods.Get<Client>((Guid)ClientId);
}
return (Client)HttpContext.Current.Items[CLIENT_KEY];
}
}
public ClientUser ClientUser
{
get
{
if (!IsAuthenticated) return null;
if (HttpContext.Current.Items[CLIENT_USER_KEY] == null)
{
HttpContext.Current.Items[CLIENT_USER_KEY] = ClientUserMethods.GetByClientId((Guid)ClientId);
}
return (ClientUser)HttpContext.Current.Items[CLIENT_USER_KEY];
}
}
public Boolean IsAuthenticated { get; set; }
public Guid? ClientId {
get
{
if (!IsAuthenticated) return null;
return (Guid)HttpContext.Current.Session["ClientId"];
}
}
public Guid? ClientUserId {
get {
if (!IsAuthenticated) return null;
return ClientUser.Id;
}
}
public int ClientTypeId {
get {
if (!IsAuthenticated) return 0;
return Client.ClientTypeId;
}
}
public Auth()
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
IsAuthenticated = true;
}
}
public void RequireClientOfType(params int[] types)
{
if (!(IsAuthenticated && types.Contains(ClientTypeId)))
{
HttpContext.Current.Response.Redirect((new UrlFactory(false)).GetHomeUrl(), true);
}
}
public void Logout()
{
Logout(true);
}
public void Logout(Boolean redirect)
{
FormsAuthentication.SignOut();
IsAuthenticated = false;
HttpContext.Current.Session["ClientId"] = null;
HttpContext.Current.Items[CLIENT_KEY] = null;
HttpContext.Current.Items[CLIENT_USER_KEY] = null;
if(redirect) HttpContext.Current.Response.Redirect((new UrlFactory(false)).GetHomeUrl(), true);
}
public void Login(string email, string password, bool autoLogin)
{
Logout(false);
email = email.Trim().ToLower();
password = password.Trim();
int status = 1;
LoginAttemptLog log = new LoginAttemptLog { AutoLogin = autoLogin, Email = email, Password = password };
try
{
if (string.IsNullOrEmpty(email)) throw new EmptyEmailException();
if (string.IsNullOrEmpty(password)) throw new EmptyPasswordException();
ClientUser clientUser = ClientUserMethods.GetByEmailExcludingProspects(email);
if (clientUser == null) throw new WrongEmailException();
if (!clientUser.Password.Equals(password)) throw new WrongPasswordException();
Client client = clientUser.Client;
if (!(bool)client.PreRegCheck) throw new EmailNotValidatedException();
if (!(bool)client.Active || client.DeleteFlag.Equals("y")) throw new InactiveAccountException();
FormsAuthentication.SetAuthCookie(client.Id.ToString(), true);
HttpContext.Current.Session["ClientId"] = client.Id;
log.KeyId = client.Id;
log.KeyEntityId = ClientMethods.GetEntityId(client.ClientTypeId);
}
catch (AuthException ax)
{
status = ax.StatusCode;
log.Success = status == 1;
log.Status = status;
}
finally
{
LogRecorder.Record(log);
}
}
}
}
過度設計的身份驗證機制的經典案例,除此之外,設計也很糟糕。
異常應該不在Auth類中,而是駐留在同一名稱空間中。 你能想象如果微軟創建了這樣的例外,.Net框架會是什么樣子。 始終保持簡單,愚蠢( KISS )。 看來你需要模塊化代碼。 嘗試簡單但模塊化 。
您的身份驗證客戶端密鑰是靜態魔術值 ,您將隨程序集一起發送。 使用SecureString而不是readonly字符串 。 任何人都可以使用Reflector來掌握它。 您如何維持變更廣告安全性?
您的代碼直接引用Current HttpContext對象,實際上您可以在將使用它的客戶端代碼中傳遞當前上下文對象的引用。
RequireClientOfType是int [] - 為什么在世界上你想要這樣做? 我相信它可能是一個枚舉或不可變的結構,如果有的話。
您已經在Login()和Logout()中使用FormsAuthentication ,這足以替換整個Auth。 如果你最終要使用FormsAuthnetication來處理Auth,你為什么要重新發明輪子?
是的,如果你不能修改這個設計,請至少使用FxCop / StyleCop來避免意大利面條代碼。
此外,您可以將Auth類設置為靜態並公開FormsAuthentication之類的功能。 並將其從Auth重命名為Authentication 。
這是http://thedailywtf.com/的主要候選人
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.