2009-11-09 2 views
0

사용자와 사이트 관리자가 내가이 길에 결정 내 응용 프로그램에서 데이터를보기/추가/수정/삭제 할 수 있도록하려면 컨트롤러 작업에서 중복 코드를 줄 mvcapp.net/을 1234/contact/add.

{다른 관리자의} 사용자가 다른 클라이언트의 데이터에 액세스하지 못하게하려면 컨트롤러 동작에 다음 코드를 추가해야합니다.

... 
    var model = repos.GetSomeData(); 
    if (User.IsInRole("Admin") == false) { 
    if (account == Profile["Client"]) 
     return View(model); 
    else 
     return View("WrongClient"); 
    } 
... 

가장 적합한 방법은 무엇입니까?

솔루션은 나는 그들이에만 해당 계좌 번호에 대한 클라이언트 데이터를 반환하도록 당신은 당신의 저장소 방법을 쓸 수

public class BaseController : Controller { 
    protected override OnActionExecuting(ActionExecutingContect filterContext) { 
     if (filterContext.RouteData.Values["account"] != null) { 
     string client = filterContext.RouteData.Values["account"].ToString(); 
     if (User.IsInRole("admin") == false) { 
      if (Profile.Clients.Contains(account) == false) 
       filterContext.Result = new ViewResult() {ViewName = "WrongClient"}; 
      } 
     } 
    } 
} 

답변

0

프로필 [ "AccountNumber"]가 수행하는 작업 (또는 프로필의 출처)을 잘 모르겠지만 언제든지 해당 개체를 만들 수 있다고 가정합니다.

는 다음 (컨트롤러에서이 장소를) 수행 할 수 있습니다

protected override void ExecuteCore() 
{ 
    var model = repos.GetSomeData(int.Parse(base.RouteData.Values["client"]))); 
    if (User.IsInRole("Admin") == false && Profile["AccountNumber"].ToString() != model.AccountNumber) 
    { 
      ViewData["Error"] = "You can't access this page"; 
      View("WrongClient").ExecuteResult(ControllerContext); 
    } 
    else 
      base.ExecuteCore(); 

} 

당신은 당신이 필요로하는 모든 컨트롤러에 넣고, 또는 컨트롤러가이 기능을 구현하는 기본 컨트롤러 클래스를 상속 할 수 있습니다.당신이 관리를하고있어 특정 사용자의 정보에 액세스해야하는 경우 (필자는 사용자를 위해 만든 같은 뷰를 사용하고자하는 가정) 어떤 http://forums.asp.net/t/1382514.aspx

+0

HttpContext.Profile –

+0

그런 경우 "client"가 사용자 ID와 일치하는지 확인하는 것이 좋습니다 (User.Identity.Name으로 clientid를 사용한다고 가정). – Omar

+0

Paul Balmire의 응답 (5 번째 또는 6 번째 항목) 내가 선택한 솔루션. –

1

갔다. 계정 번호를 저장소 방법으로 전달하십시오.

사용자 정보를 저장소 메소드에 전달하는 데 관심이있는 경우 (Jabe는 아래 주석에서 설명 함) 저장소에서 IQueryable을 반환하고 보안 트리밍을 수행하기 위해 Linq 쿼리를 실행할 수 있습니다.

+0

:

아이디어에서 가져온? – Omar

+0

admin 플래그도 저장소 메소드에 전달할 수 있습니다. –

+0

아마도 논란의 여지가 있지만 저장소는 사용자에 대해 알지 않아야합니다. IMHO는 "ID를주고 데이터를 얻는 것"과 같아야합니다. – Jabe

0

이 특정 예에서 Azam Sharp는 blog에 가능한 해결책이 있습니다. 나는 문자 그대로 5 분 전에이 기사를 우연히 발견했다. 희망이 도움이됩니다!

+0

다시보기 - 이것은 당신의 필요를 직접적으로 다루지는 못하지만, 여전히 당신이하려는 일에 적응할 수 있다고 생각합니다. –

+0

나는 블로그 포스터가 삭제를 처리하는 방식에 대해별로 신경 쓰지 않는다. 삭제 작업은 항상 GET이 아니라 POST에 의해 수행되어야합니다. –

+0

@ 로버트 - 일반적으로 동의합니다. 나는 구현과 반대되는 기사의 일반적인 아이디어에 더 관심이 많다. BaseController가 수행 할 수있는 좋은 예입니다. –

0

프로필에서 처분 한 정보를 이미 고려 했으므로 클라이언트를 실제로 경로에 포함시켜야합니까?

저장소 수준 (위에서 언급 한 것처럼)을 처리하는 한, 약간의 교묘함이 발생할 수 있습니다. 이는 일부 비즈니스 프로세스에서 내부적으로 필요한 데이터에 대한 액세스를 차단하고 사용자가 액세스하지 못하게 할 수 있습니다. 물론 이것을 처리하기 위해 필터링 된/필터링되지 않은 메서드를 별도로 만들 수 있습니다. 또한 이것은 클라이언트 데이터의 혼합이 허용 될 수있는 방법이 될 수 없습니다.

대부분의 경우 우리 응용 프로그램에서는 추가/삽입/삭제되는 최상위 항목이며 액세스가 제한되어 있어야합니다. 또한이 방식으로 제한되어야하는 제한된 데이터 집합이기 때문에 일반적으로 해당 항목에 대한 액세스 규칙을 위반하면 컨트롤러에서 일종의 예외를 throw하는 코드를 작성합니다.

앱 규칙이 매우 비슷한 경우 코드 반복을 방지 할 수있는 여러 가지 방법이 있습니다. 사용자 정의 ActionFilter 또는 사용자 정의 Controller 기본 클래스가 모두 고려됩니다. db의 각 행에 클라이언트 ID가 있거나 이와 같은 스키마가있는 경우 다른 옵션은 도메인 객체가이 ID를 노출하는 인터페이스를 구현하도록하는 것입니다. 그런 다음이 인터페이스를 다양한 보안 규칙을 적용하기위한 기초로 사용하는 재사용 가능한 코드 (mixin 스타일 확장 메서드 등)를 작성할 수 있습니다.

+0

경로에 클라이언트가있을 필요는 없습니다. 사용자 (고객 및 관리자)가 더 쉬울 것이라고 생각했습니다. –

+0

실제로 사용자가 더 어려워 보이지 않습니까? 특정 URL에 직접 액세스하려면 클라이언트 ID도 입력해야합니다. 위의 코드를 보면이 값을 이미 "알려진"프로파일 값과 비교하여 유효성을 검사해야합니다. 내가 뭔가를 놓치지 않는다면 (꽤 가능하다)이 모든 것이 완전히 불필요한 것처럼 보인다. 프로필에 포함 된 값이 안전하고 정확하면 경로 값을 전혀 다룰 필요가 없습니다. – Krazzy

+0

내 고객은 하나 이상의 계좌 번호를 가지고 있으며이를 알고 있습니다. 그들의 삶, 일명 $$은이 숫자에 달려 있습니다. 그것이 불필요하다는 것을 의미하지는 않습니다. 항상 목록에서 선택하지 않아도되는 아이디어. –