1

나는 매우 일반적인 작업이라고 생각되는 방향으로 어느 방향으로 나아갈 지 조금 넘는 장애물을 맞았습니다. 로그인 한 사용자가 데이터를 편집 할 수있는 곳은 어디에서 확인합니까? 이 경우 User에는 Id, EmailAddress, Name 및 Address 개체의 컬렉션이 있습니다. Address에는 여러 속성이 포함되어 있습니다. 하나는 UserId로, UserId는 사용자가 속한 사용자의 ID입니다. 사용자는 속한 객체 인 Address 만 편집 할 수 있습니다. Address을 편집 할 때/사용자가이를 확인할 수 있는지 확인합니다.편집 사용자 세부 정보에 대한 액세스 권한 확보

저는 이번 주에 ASP.NET MVC3을 배웠으며 연습하게되었습니다. 기본 MembershipProvider를 사용하여 사용자를 기록하는 웹 응용 프로그램을 만들었습니다 (나중에이 응용 프로그램을 사용자 정의 공급자로 바꿀 것입니다). 최종 결과는 로그인 후 컨트롤러의 User.Identity.Name 속성이 사용자 전자 메일 주소를 반환한다는 것입니다.

사용자가 세부 정보를 보려는 경우 에서 Addresses 작업을 호출합니다. 아래.

[Authorize] 
public ActionResult Addresses() 
{ 
    IEnumerable<Address> addresses = _myService.GetUserAddresss(User.Identity.Name)); 
    return View(addresses); 
} 

이제 사용자들은 주소를 확인하고 표시하는 작업을 호출 할 수 있습니다 주소 세부 사항을 편집하고자하는 경우, 그리고 액션이 주소로 편집 내용을 저장 할 수 있습니다.

[Authorize] 
public ActionResult Address(int id) 
{ 
    Address address= _myService.GetAddress(id)); 
    return View(address); 
} 

[Authorize] 
[HttpPost] 
public ActionResult Address(EditAddressModel model) 
{ 
    Address address = _myService.SaveDetail(model.Address)); 
    return View(address); 
} 

상기 방법의 결함이며, 사용자가 URL을 방문하면 ../Account/Address/12있다. 그런 다음 생성 여부에 관계없이 ID가인 경우 (존재하는 경우)이를보고 편집 할 수 있습니다.

나는 N 계층 접근 방식을 따르고 있습니다. 그래서 컨트롤러는 비즈니스 로직 계층과 대화하는 서비스에 대해 이야기합니다.이 서비스는 리포지토리와 통신하며 마침내 Entity Framework 4를 사용하여 데이터베이스와 통신합니다. 권한 부여 확인은 어디에서 수행되어야합니까?

다음 해결책을 고려했지만 적절한 접근 방식을 결정할 수 없습니다. 상기 제어기는 상기 User.Identity.Name 속성에 대한 액세스를 갖는 한 컨트롤러 클래스 아이디어 1

. 이 속성을 사용하면 서비스에서 반환 된 주소의 사용자 ID가 현재 로그인 한 사용자와 일치하는지 확인할 수 있습니다. 그렇지 않은 경우 오류 페이지를 표시하고, 그렇지 않으면 정상적으로 보거나 편집하게하십시오.

장점 - 간단한 구현으로 서비스가 Address 개체를 반환 한 후에 추가 if 문을 추가하기 만하면됩니다. 컨트롤러가 User.Identity.Name에 액세스 할 수 있습니다.

단점 - 컨트롤러에 사용자가 볼 수 없음을 결정하기 위해 데이터가 컨트롤러로 반환됩니다. "오직 사용자 만이 자신의 주소를 편집 할 수 있습니다"라는 비즈니스 로직과 같은 느낌이 컨트롤러에 들끓었습니다.

비즈니스 계층

아이디어 2. 컨트롤러는 userId 및 detailId (_myService.GetAddress(User.Identity.Name, detailId));)를 사용하여 서비스를 호출하고 차례로 비즈니스 계층을 호출합니다. 비즈니스 계층에 메서드가 있습니다. public Address GetAddress(int userId, int addressId) 비즈니스 계층이 데이터베이스에서 Address을 가져 오도록 요청되면 반환 된 주소가 사용자의 것인지 확인한 다음 반환합니다. 그렇지 않은 경우, null을 리턴합니다. 따라서 컨트롤러는 서비스에서 Null 응답을 받고 적절한 오류 메시지를 표시합니다.

장점 - 세부 정보만을 편집하는 사용자의 비즈니스 논리는 비즈니스 계층에 있습니다.

불만족 - 비즈니스 논리가 User.Identity.Name에 액세스 할 수 없으므로 서비스 및 비즈니스 클래스의 각 메소드에 userId 매개 변수가 필요하며 이는 잘못된 불필요한 확장을 유발합니다. 위와 3

아이디어, 서비스 및 비즈니스 계층 클래스를 제외하고, 사용자 아이디라는 속성이 있습니다. 사용자가 데이터베이스 자원에 액세스 할 수 있는지 점검하는 데 사용됩니다. 이것은 생성 도중 또는 서비스를 호출하기 전에 설정할 수 있습니다. 즉

[Authorize] 
public ActionResult Address(int id) 
{ 
    _myService.User = User.Identity.Name; 
    Address address = _myService.GetAddress(id)); 
    return View(address); 
} 

장점 - 비즈니스 세부 정보를 편집하는 사용자의 비즈니스 논리는 비즈니스 계층에 있습니다. userId를 각 메서드 호출에 전달할 필요가 없습니다.

불만족 -이 방법을 사용한 예를 본 적이 없습니다. 그리고 나는 그것이 옳다고 생각하지 않습니다. WCF를 서비스 계층으로 사용하고있는 것은 아닙니다. 그러나 만약 내가 그렇다면,이 여분의 재산을 가지고 일하지 않을 것이라고 확신합니다.

아이디어 4

액세스 제어기로부터 비즈니스 계층에 서비스 비록 통과하지 않고 비즈니스 계층에서 User.Identity.Name. 가능한 경우 확실하지 않습니다.

답변

1

비즈니스 로직 계층에서 권한 부여를하는 것이 좋습니다. 응용 프로그램에서 원하는 위치 (동일한 응용 프로그램 도메인 인 경우)에서 현재 사용자의 주체에 액세스 할 수 있습니다. 정적 멤버 HttpContext.Current에 액세스하면 현재 HttpContext에 대한 사용자 주체를 검색 할 수 있습니다.

Principal HttpContext.Current.User

물론,이 코드를 포함하는 어셈블리 System.Web을 참조해야 할 것이다. 나는 이것이 웹 어플리케이션에서 큰 관심사가 될 것이라고 생각하지 않는다.

비즈니스 로직을 호출에서이 정적 멤버로 분리하려면 Adapter pattern을 사용하여 호출을 닫고 사용자의 원칙을 검색하는 것이 좋습니다. 이 방법으로 다른 인증/권한 프레임 워크를 선호하여 회원 자격을 없애거나 HttpContext.Current에 대한 구체적인 결합이없는 경우 조롱하도록 선택할 수 있습니다.

다음은 현재 컨텍스트의 사용자 원칙에 액세스하는 어댑터의 예입니다.

public interface IUserAdapter 
{ 
    IPrincipal GetUserPrincipal(); 
    void SetAuthenticationCookie(IUser user); 
    void SignOut(); 
} 

// my business logic representation of a user 
public interface IUser 
{ 
    int Id { get; set; } 
    string Name { get; set; } 
} 

public class WebUserAdapter : IUserAdapter 
{ 
    public IPrincipal GetUserPrincipal() 
    { 
     return HttpContext.Current.User; 
    } 

    public void SetAuthenticationCookie(IUser user) 
    { 
     FormsAuthentication.SetAuthCookie(user.Id.ToString(), false); 
    } 

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

이것은 사용자 X가 사용자 y의 데이터를 쿼리하지 않도록 데이터 규칙을 어떻게 적용합니까? 이러한 비즈니스 논리는 이러한 검사에서 실패하므로 일반적으로 db의 관계로 저장됩니다. –

+0

이 대답에서 내가 시도한 요점은 비즈니스 논리에서 현재 사용자의 보안 주체에 액세스 할 수 있다는 것입니다. 사용자가 요청 된 레코드에 대한 액세스 권한을 갖고 있는지 확인하려면 데이터 계층을 호출하여 데이터를 검색하기 전에 관계가 있는지 여부를 확인해야합니다. 이 쿼리의 결과는 비즈니스 로직에서 다음 단계를 결정하는 데 사용됩니다. –

1

모든 검색어에 사용자의 ID를 포함하기 만하면됩니다. 아이디어 2에서이 작업을 수행했습니다. 보안 감사의 일환으로이 작업을 팀의 일원으로 수행 할 경우 모든 데이터 액세스 메소드에 매개 변수가 포함되도록하고 쿼리의 해당 사용자 ID 또는 이름을 where 절에있는 DB에 사용합니다. 통합 테스트는 사용자에 대한 하나의 레코드를 생성하고 다른 사용자 이름 매개 변수를 전달하는 메소드를 호출하여 ID로로드하려고 시도하는 데 도움이 될 수 있습니다.

+0

답변 해 주셔서 감사합니다. 이것은 Asp.net에 대해 배울 수있는 작은 프로젝트이므로 비즈니스 논리에서 현재 사용자에게 액세스하는 더 간단한 솔루션이라고 생각합니다. – JonWillis

+0

나는 체크를 잊어 버릴 수도있는 곳에 주입을 막기 위해이 파라미터가 데이터 레이어에 전달되어야한다는 것을 절대 강조 할 수 없다.당신이이 calue를 읽는 곳은 아무런 차이가 없다. 비즈니스 계층 등 (저장소 계층은 더 의미가있다. 또는 적어도 저장소 계층이이 값에 접근 할 수 있도록 보장한다.) 내 게시물은 제한된 쿼리 . –

+0

로그인 된 사용자 값이 비즈니스 계층에서 검색되고 리포지토리에 전달됩니다. 이 모델은 승인되지 않은 액세스를 방지하기 위해 사용자/주소 일치를 검사합니다. – JonWillis

관련 문제