Просмотрите мой код аутентификации ASP.NET - PullRequest
2 голосов
/ 06 января 2010

У меня были некоторые проблемы с аутентификацией в 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);
            }

        }

    }

}

Ответы [ 2 ]

8 голосов
/ 06 января 2010

Классический корпус с чрезмерной инженерией Механизм аутентификации и, кроме того, дизайн плохой.

  • Исключения должны быть вне класса Auth, но находиться в том же пространстве имен. Можете ли вы представить, как будет выглядеть .Net framework, если Microsoft создала подобные исключения. Всегда держите это простым, глупым ( KISS ). Кажется, вам нужен модульный код. Попробуйте быть простым, но модульным .

  • Ваши клиентские ключи аутентификации являются статическими magic-values ​​, и вы отправляете их вместе со своими сборками. Используйте SecureString вместо readonly string . Любой может получить его с помощью Reflector. Как вы поддерживаете изменения безопасности объявлений?

  • Ваш код напрямую ссылается на объект Current HttpContext , когда фактически вы могли передать ссылку на текущий объект контекста в коде клиента, который будет использовать это.

  • RequireClientOfType is int [] - почему в мире вы хотите это сделать? Я полагаю, что это могло бы быть перечислением или неизменной структурой, если она вообще когда-либо понадобилась.

  • Вы уже используете FormsAuthentication в вашем Login () и Logout (), что достаточно для замены всего вашего Auth. Почему вы хотите заново изобрести колесо, если в конечном итоге вы собираетесь использовать FormsAuthnetication, чтобы позаботиться об аутентификации.

  • И да, если вы не можете пересмотреть этот дизайн, пожалуйста, используйте FxCop / StyleCop как минимум, чтобы избежать спагетти-кода.

  • Также вы можете сделать класс Auth как статическим и предоставить такие функции, как FormsAuthentication. А также переименуйте его из Auth в Authentication .

Это главный кандидат на http://thedailywtf.com/

3 голосов
/ 06 января 2010

Попробуйте использовать встроенный asp.net Аутентификация с помощью форм (Членство).

Вы можете узнать из этих видео:

Ссылка1 и Ссылка2

Если вы хотите настроить его, посмотрите это видео:

Ссылка

...