2011-02-03 2 views
3

MVC 신참 질문 : & 프로젝트를 실행 중입니다. 정상적으로 작동합니다. 이제 특정 뷰 (심지어는 전체 컨트롤러)에 대한 액세스를 제한하려고합니다. VS 2010 패키지에는 사용자 이름과 암호를 저장하는 약간 축소 된 데이터베이스를 포함하여 표준 내장 보안 모듈이 포함되어 있습니다. - 비표준 접근 방식을 사용합니다.ASP.NET MVC 보안 용 빠른 시작

음, 내장 보안을 사용하고 싶지 않습니다. 내 자신의 사용자 테이블을 가지고 있고, 암호를 직접 암호화하는 방법을 알고 있습니다. 정말 고마워요. 내가하고 싶은 일은 로그인 방법입니다. 로그인이 성공했다고 판단되면 세션을 인증 된 것으로 설정하고 사용자가 제한된보기에 액세스 할 수있게하려고합니다. 너무 어려워서는 안된다, 그렇지?

저는 인터넷 보안에 대해 봤습니다. 문제는 정보의 부족이 아니라 오히려 너무 많은 것입니다. 누군가 내 개인 OutOfMemoryException을 잘라 내 상황에 적용 할 수있는 "빠른 시작"을 제공하면 정말 감사하겠습니다 ...

답변

4

ASP.NET에 대한 좋은 점 중 하나는 매우 확장 성이 있다는 것입니다. 예, 인증 및 권한 부여의 기본 모델은 ASP.NET 제공 멤버십 테이블을 별도의 데이터베이스에 사용하거나 직접 추가하는 것입니다. 다행히도, 그 주위에 방법이 있습니다.

원하는 작업을 달성하는 가장 쉽고 적절한 방법은 기존 데이터베이스를 사용하는 사용자 지정 MembershipProvider를 만드는 것입니다.

MSDN - Implementing a Membership Provider

+0

Ok ... 맞춤 멤버십 제공 업체를 만들었습니다 ... 이제 어떻게해야합니까? –

+0

@Shaul - web.config를 수정하여 기본값 대신 사용자 정의 멤버십 공급자를 사용합니다. –

+0

좋습니다 ... 점점 가까워지고 있습니다. 이제 회원 공급자에게 사용자가 인증되었음을 알리는 방법은 무엇입니까? –

1

이 코드를 가이드로 사용하여 우리 자신의 모델과 데이터베이스를 사용하여 poeple을 로그 아웃합니다. IdentitySession 클래스는 컨트롤러에서 사인 인 된 사용자 데이터를 가져올 수 있습니다. 나는 약간을 여기에서 잘라서 우리 코드를 단순화하려고 노력했다. 그래서 이것이 단지 달릴 것을 기대하지 말아라. 희망이 도움이됩니다.

public ActionResult Login(int pageId) { 
    ViewData["ReturnUrl"] = Request["ReturnUrl"]; 
    return View(Cms3Configuration.DefaultViewModelWithPage(attachedPage)); 
} 

public ActionResult Process(int pageId, string login, string password, string ReturnUrl) { 
    var user = userRepository.GetByUserName(login); 
    ViewData["ReturnUrl"] = ReturnUrl; 
    if (user != null && authenticator.VerifyAccount(user, password)) { 
    authenticator.SignIn(user); 
    if (ReturnUrl.IsNotEmpty()) { 
     return Redirect(ReturnUrl); 
    } 
    return Redirect("~" + attachedPage.Parent.Url); 
    } 
    ////login failed 
    TempData[TempDataKeys.Error] = "Invalid login"; 
    return RedirectToAction("Login", new { pageId = pageId, ReturnUrl }); 
} 

public ActionResult Logout(int pageId) { 
    authenticator.SignOut(); 
    return RedirectToAction<LoginController>(x => x.Login(pageId), new {pageId = pageId}); 
} 

public interface IAuthenticator { 
    void SignIn(User person); 
    IIdentity GetActiveIdentity(); 
    WindowsPrincipal GetActiveUser(); 
    void SignOut(); 
    bool VerifyAccount(User person, string password); 
    bool HasRole(string person, string role); 
} 

public class Authenticator : IAuthenticator { 
    private readonly IHttpContextProvider _httpContextProvider; 
    private readonly ICryptographer _cryptographer; 
    private readonly IRepository repository; 

    public Authenticator(IHttpContextProvider httpContextProvider, ICryptographer cryptographer, IRepository repository) { 
    _cryptographer = cryptographer; 
    this.repository = repository; 
    _httpContextProvider = httpContextProvider; 
    } 

    public void SignIn(User user) { 
    FormsAuthentication.SignOut(); 
    if (user == null) 
     return; 
    DateTime issued = DateTime.Now; 
    DateTime expires = issued.AddMinutes(30); 
    if (user.ExpiryDate.HasValue) { 
     if (user.Expires && expires > user.ExpiryDate) 
     expires = (DateTime) user.ExpiryDate; 
    } 
    var roles = user.Roles.Select(x => x.Name).ToList(); 
    var ticket = new FormsAuthenticationTicket(1, user.UserName, issued, expires, false, string.Join(",", roles.Distinct().ToArray())); 
    var encryptedTicket = FormsAuthentication.Encrypt(ticket); 
    var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket) { Expires = ticket.Expiration }; 
    _httpContextProvider.GetCurrentHttpContext().Response.Cookies.Add(authCookie); 
    } 

    public IIdentity GetActiveIdentity() { 
    var httpcontext = _httpContextProvider.GetCurrentHttpContext(); 
    if (httpcontext == null || httpcontext.User == null) 
     return null; 
    return httpcontext.User.Identity; 
    } 

    public WindowsPrincipal GetActiveUser() { 
    return _httpContextProvider.GetCurrentHttpContext().User as WindowsPrincipal; 
    } 

    public void SignOut() { 
    FormsAuthentication.SignOut(); 
    } 

    public bool VerifyAccount(User person, string password) { 
    string passwordHash = _cryptographer.HashPassword(password, person.PasswordSalt); 
    return passwordHash == person.Password && !person.HasExpired() && person.Approved == true; 
    } 

} 

public interface IIdentitySession<T> { 
    T GetLoggedInIdentity(); 
    bool IsAuthenticated { get; } 
    bool IsAdministrator { get; } 
} 

public class IdentitySession<T> : IIdentitySession<T> where T : Identity { 
    private readonly IAuthenticator<T> authenticator; 
    private readonly IRepository repository; 
    private readonly IHttpContextProvider httpContextProvider; 
    private T currentIdentity; 
    private static readonly object _lock = new object(); 

    public IdentitySession(IAuthenticator<T> authenticator, IRepository repository, 
         IHttpContextProvider httpContextProvider) { 
    this.authenticator = authenticator; 
    this.activeDirectoryMapper = activeDirectoryMapper; 
    this.repository = repository; 
    this.httpContextProvider = httpContextProvider; 
    } 

    public virtual T GetLoggedInIdentity() { 
    IIdentity identity = authenticator.GetActiveIdentity(); 

    if (identity == null) 
     return null; 

    if (!identity.IsAuthenticated) 
     return null; 

    lock (_lock) { 
     if (currentIdentity == null) { 
     currentIdentity = repository.Query<T>().Where(x => x.UserName == identity.Name).FirstOrDefault(); 
     } 
    } 

    return currentIdentity; 
    } 

    public bool IsAuthenticated { 
    get { return httpContextProvider.GetCurrentHttpContext().User.Identity.IsAuthenticated; } 
    } 

    public bool IsAdministrator { 
    get { return false; } 
    } 
} 
+0

오와 IdentitySession은 Unity Resolver를 사용하여 Request Lifetime을 갖도록 설정되어 있습니다. – Richard

1

나는 당신을 건의 할 것입니다 : 이렇게하면 당신은 아직도 당신의 컨트롤러에 속성을 통해 작업에 대한 액세스를 제어 할 수 있음을 의미 기존의 ASP.NET MVC 인증 프레임 워크에 사용자 정의 인증 논리를 연결 할 수 있습니다 FormsAuthenticationService를 사용하여 만족 한 후에 사용자를 서명해야합니다.

보일러 플레이트 MVC3 인터넷 응용 프로그램 프로젝트 템플릿은 이에 대한 몇 가지 지침을 제공합니다 (회원 코드를 회원 코드로 바꾸십시오).

코드에 대한 액세스를 제한하려면 CodeAccessSecurity 및 Permission 특성을 사용할 수 있습니다. 이러한 특성은 클래스 및 메서드 수준에서 적용 할 수 있습니다. 예 :

[System.Security.Permissions.PrincipalPermission(SecurityAction.Demand, Authenticated = true, Role = "Admin")] 
public ActionResult Index() 
{ 
.... 
} 

물론 web.config 파일을 사용하여 웹 사이트 영역에 대한 사용 권한을 설정할 수 있습니다.