查看我的ASP.NET身份验证代码

Nie*_*sma 2 c# asp.net authentication

我在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);
            }

        }

    }

}
Run Code Online (Sandbox Code Playgroud)

thi*_*eek 8

过度设计的身份验证机制的经典案例,除此之外,设计也很糟糕.

  • 异常应该不在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/的主要候选人