2012-01-27 3 views
3

지금까지 MVC3 앱에서 모든 인증 작업을 수행했습니다. 즉, 구성원 유효성을 검사하고 내 MemberRepository 클래스를 통해 구성원을 만들었습니다. 나는 지금 관례에, MembershipProvider와 더불어 가고 싶으면. 지금까지는이 클래스의 ValidateUser 메서드를 재정의해야한다는 것을 모았으며 Login 컨트롤을 사용하지 않았기 때문에 절대적으로이 작업을 수행해야하는지 확신 할 수 없습니다. GetUserCreateUser 같은MVC3에서 재정의 할 MembershipProvider의 양

재정의 방법은 내가 정교하게 제작 된 Member 클래스가 MembershipUser처럼, 내 파티에 초대받지 않은 유형을 제공합니다. 기본 제공 컨트롤이나 관리 도구를 사용하지 않을 경우 사용자 정의 멤버십 공급자가 필요한지 여부에 관계없이 누군가 제게 알맞게 정리할 수 있습니까? 그렇게 할 경우 내 우선 적용을 절대적으로 필요한 수준으로 제한해야합니까? 그게 뭐야?

+1

[사용자 지정 멤버십 공급자 만들기] –

+0

감사합니다 @ 로버트,하지만 내 질문에 대답하지 않습니다. 맞춤 멤버 공급자를 만드는 방법을 알고 기본 방법을 재정의해야하는 정도를 묻습니다. NotImplementedException에 그것들을 모두 남겨 두십시오. 그렇게 할 수 있다면, 커스텀 공급자가 정말로 필요한가요? – ProfK

답변

1

사용자는 MembershipProvider

당신이는 MembershipProvider를 사용하는 경우 "무료"멋진 보안 기능을 얻을 수 있습니다 : 당신은 로그인에 모든 인증되지 않은 사용자를 리디렉션의 Web.config를 설정할 수 있습니다 예를 들어, 페이지. 또는 특정 역할을 가진 사용자에게만 표시되도록 사이트의 특정 부분을 설정할 수 있습니다. 이러한 기능이 프로젝트에 적합하지 않거나 다른 기능을 이미 구현하고있는 경우 사용자 지정 MembershipProvider를 구현하는 데 별 도움이되지 않습니다. 당신이 실제로 회원 기능을 처리하기 위해 SqlMembershipProvider를 사용하도록 구현을 전환됩니다 고려할 수 있습니다

SqlMembershipProvider

또 다른 가능성.

SqlMembershipProvider는 계정 생성, 유효성 검사, 삭제, 잠금, 암호 재설정, 기본 역할 등 모든 프로젝트를 다시 작성해야하는 성가신 일반적인 작업에 대해 강력하고 입증 된 플랫폼을 제공합니다. 이 모든 것 자신 없이을 사용하면 SqlMembershipProvider를 사용하여 실제로 그것을 생성하기위한 포인트를 만들지 않습니다. 그러나 자신의 구현에서 잘못된 일을했을 가능성이 있기 때문에 조심해야합니다. 예 :

  • 비밀번호를 일반 텍스트 또는 해시로 저장 하시겠습니까?
  • Rainbow Table 공격에 공개 되었습니까, 아니면 해시를 염화하고 있습니까?
  • 비밀번호가 50 회 이상 잘못 입력 된 경우 사람들의 계정을 잠 그거나 해커가 다른 사람의 계정에 무차별 공격을 가하기 전까지는 계속 해고 당할 수 있습니까?

SqlMembershipProvider는 이미 이러한 모든 문제를 쉽게 구성 할 수있는 방식으로 처리했습니다. 자신 만의 멤버쉽 인터페이스를 원할 수도 있습니다. DTO는이 기본 멤버쉽 공급자를 단순히 감싸기 만하면되므로 이러한 다양한 문제에 대해 걱정할 필요가 없습니다. 그렇게하면 대부분의 코드가 이러한 "초대받지 않은 유형"과 상호 작용할 필요가 없지만 백 엔드에서 널리 사용되고 입증 된 보안 프레임 워크의 이점을 얻을 수 있습니다.

+0

나는 그것을 멋지게 요약했다고 생각한다. 고마워. 커스텀 프로 바이더 나 SqlProvider는 필요하지 않지만, 많은 경우 해당 프로 바이더와 좋은 점이 있습니다. – ProfK

2

여기는 단위 테스트를 위해 작성한 것입니다. 그것은 가능한 한 최소화합니다.

public class MockMembershipProvider : MembershipProvider 
{ 
    public IList<MembershipUser> Users { get; private set; } 

    private string _applicationName; 
    public override string ApplicationName 
    { 
     get 
     { 
      return _applicationName; 
     } 
     set 
     { 
      _applicationName = value; 
     } 
    } 

    public override bool ChangePassword(string username, string oldPassword, string newPassword) 
    { 
     throw new NotImplementedException(); 
    } 

    public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer) 
    { 
     throw new NotImplementedException(); 
    } 

    public override MembershipUser CreateUser(
     string username, 
     string password, 
     string email, 
     string passwordQuestion, 
     string passwordAnswer, 
     bool isApproved, 
     object providerUserKey, 
     out MembershipCreateStatus status) 
    { 
     var user = new MembershipUser(ProviderName, username, username, email, passwordQuestion, null, isApproved, false, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now); 
     Users.Add(user); 
     status = MembershipCreateStatus.Success; 
     return user; 
    } 

    public override bool DeleteUser(string username, bool deleteAllRelatedData) 
    { 
     var u = Users.Where(mu => mu.UserName.Equals(username, StringComparison.OrdinalIgnoreCase)).FirstOrDefault(); 
     if (u == null) return false; 
     Users.Remove(u); 
     return true; 
    } 

    public override bool EnablePasswordReset 
    { 
     get { return false; } 
    } 

    public override bool EnablePasswordRetrieval 
    { 
     get { return false; } 
    } 

    public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) 
    { 
     throw new NotImplementedException(); 
    } 

    public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) 
    { 
     var users = (from u in Users 
        where u.UserName.Equals(usernameToMatch, StringComparison.OrdinalIgnoreCase) 
        select u).ToList(); 
     totalRecords = users.Count; 
     return ToMembershipUserCollection(users); 
    } 

    public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) 
    { 
     var list = Users.Skip(pageIndex * pageSize).Take(pageSize); 
     totalRecords = list.Count(); 
     var result = new MembershipUserCollection(); 
     foreach (var u in list) 
     { 
      result.Add(u); 
     } 
     return result; 
    } 

    public override int GetNumberOfUsersOnline() 
    { 
     return Users.Count(); 
    } 

    public override string GetPassword(string username, string answer) 
    { 
     throw new NotImplementedException(); 
    } 

    public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) 
    { 
     return (from u in Users 
       where u.ProviderUserKey.ToString() == providerUserKey.ToString() 
       select u).FirstOrDefault(); 
    } 

    public override MembershipUser GetUser(string username, bool userIsOnline) 
    { 
     return (from u in Users 
       where u.UserName.Equals(username, StringComparison.OrdinalIgnoreCase) 
       select u).FirstOrDefault(); 
    } 

    public override string GetUserNameByEmail(string email) 
    { 
     return (from u in Users 
       where u.Email.Equals(email, StringComparison.OrdinalIgnoreCase) 
       select u.UserName).FirstOrDefault(); 
    } 

    public override int MaxInvalidPasswordAttempts 
    { 
     get { return 3; } 
    } 

    public override int MinRequiredNonAlphanumericCharacters 
    { 
     get { return 1; } 
    } 

    public override int MinRequiredPasswordLength 
    { 
     get { return 6; } 
    } 

    public override int PasswordAttemptWindow 
    { 
     get { return 10; } 
    } 

    public override MembershipPasswordFormat PasswordFormat 
    { 
     get { throw new NotImplementedException(); } 
    } 

    public override string PasswordStrengthRegularExpression 
    { 
     get { return null; } 
    } 

    public override string Name 
    { 
     get 
     { 
      return ProviderName; 
     } 
    } 

    public string ProviderName { get; set; } 

    public override string ResetPassword(string username, string answer) 
    { 
     throw new NotImplementedException(); 
    } 

    public override bool RequiresQuestionAndAnswer 
    { 
     get { return false; } 
    } 

    public override bool RequiresUniqueEmail 
    { 
     get { return true; } 
    } 

    private MembershipUserCollection ToMembershipUserCollection(IEnumerable<MembershipUser> users) 
    { 
     var result = new MembershipUserCollection(); 
     foreach (var u in users) 
     { 
      result.Add(u); 
     } 
     return result; 
    } 

    public override bool UnlockUser(string userName) 
    { 
     return true; 
    } 

    public override void UpdateUser(MembershipUser user) 
    { 
     var oldUser = Users.Where(u => u.UserName.Equals(user.UserName, StringComparison.OrdinalIgnoreCase)).Single(); 
     var index = Users.IndexOf(oldUser); 
     Users[index] = user; 
    } 

    public override bool ValidateUser(string username, string password) 
    { 
     throw new NotImplementedException(); 
    } 

    public MockMembershipProvider() 
    { 
     this.ProviderName = "MockMembershipProvider"; 
     Users = new List<MembershipUser>(); 
    } 
} 

public class FakeMembershipProvider : MockMembershipProvider 
{ 
    public FakeMembershipProvider(string name) 
    { 
     this.ProviderName = name ?? "MockMembershipProvider"; 
    } 
    public override MembershipUser CreateUser(
     string username, 
     string password, 
     string email, 
     string passwordQuestion, 
     string passwordAnswer, 
     bool isApproved, 
     object providerUserKey, 
     out MembershipCreateStatus status) 
    { 
     status = MembershipCreateStatus.ProviderError; 
     var user = new MockMembershipUser(); 
     user.Password = password; 
     user.User = username; 
     user.UserKey = providerUserKey; 
     Users.Add(user); 
     status = MembershipCreateStatus.Success; 
     return user; 
    } 
} 

public class MockMembershipUser : MembershipUser 
{ 
    public string Password { get; set; } 
    public string User { get; set; } 
    public object UserKey { get; set; } 

    public override string UserName { get { return User; } } 

    public override string Comment { get; set; } 

    public override object ProviderUserKey { get { return UserKey; } } 

    public override string GetPassword() 
    { 
     return Password ?? string.Empty; 
    } 
1

MembershipRepository에서 웹 응용 프로그램을 분리 하시겠습니까?

그렇다면 custom MembershipProvider에 동일한 기능을 모두 구현하여 응용 프로그램이 .NET Membership classes (web.config 제외)에만 종속되도록합니다.

그렇지 않다면 신경 쓰지 마세요.

+0

> MembershipRepository에서 웹 응용 프로그램을 분리 하시겠습니까? 아니요, 내 DI가 이미 처리 한 것 이상입니다. 나는 어딘가에서 공급자가 필요하다는 인상을 받았습니다. – ProfK

+0

로그인 컨트롤은 기본적으로 기본 MembershipProvider를 사용하지만 쉽게 재정의 할 수 있습니다. Membership 도우미 클래스 (및 비슷한 역할)를 사용하고 싶지 않은 경우 커스텀 공급자를 만들어서 얻을 수있는 게 없다고 생각합니다. – jrummell

관련 문제