2

MVC 프로젝트에서 일하고 있습니다. 사용자 지정 권한 특성을 사용하려고합니다. 우선 this blog post에 예를 사용했습니다.Asp.Net MVC 사용자 정의 권한 부여가 작동하지 않습니다.

public class CustomAuthorizeAttribute : AuthorizeAttribute 
{ 
    public string RolesConfigKey { get; set; } 

    protected virtual CustomPrincipal CurrentUser => HttpContext.Current.User as CustomPrincipal; 

    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if (!filterContext.HttpContext.Request.IsAuthenticated) return; 
     var authorizedRoles = ConfigurationManager.AppSettings["RolesConfigKey"]; 

     Roles = string.IsNullOrEmpty(Roles) ? authorizedRoles : Roles; 

     if (string.IsNullOrEmpty(Roles)) return; 
     if (CurrentUser == null) return; 
     if (!CurrentUser.IsInRole(Roles)) base.OnAuthorization(filterContext); 
    } 

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     if (!filterContext.HttpContext.Request.IsAuthenticated) return; 
    } 
} 

기본 컨트롤러에서이 사용자 지정 보안 주체를 사용합니다. 내 내 기본 경로를 routeconfig에서

public class CustomPrincipal : IPrincipal 
{ 
    public CustomPrincipal(string userName) { this.Identity = new GenericIdentity(userName); } 

    public bool IsInRole(string userRoles) 
    { 
     var result = true; 
     var userRolesArr = userRoles.Split(','); 
     foreach (var r in Roles) 
     { 
      if (userRolesArr.Contains(r)) continue; 
      result = false; 
      break; 
     } 
     return result; 
    } 

    public IIdentity Identity { get; } 
    public string UserId { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string[] Roles { get; set; } 
} 

는 사용자의 작업을 로그인 /Account/Index이다. 그리고 이것은 계정 컨트롤러 색인 작업입니다. 사용자가 관리자 역할에있을 때 당신이 볼 수 있듯이

[HttpPost, ValidateAntiForgeryToken] 
    public ActionResult Index(AccountViewModel accountModel) 
    { 
     var returnUrl = string.Empty; 

     if (!ModelState.IsValid) { return UnsuccessfulLoginResult(accountModel.UserName, ErrorMessages.WrongAccountInfo); } 

     var account = _accountService.CheckUser(accountModel.UserName, accountModel.Password); 
     if (account == null) return UnsuccessfulLoginResult(accountModel.UserName, ErrorMessages.WrongAccountInfo); 

     var roles = account.Roles.Select(r => r.RoleName).ToArray(); 
     var principalModel = new CustomPrincipalModel 
     { 
      UserId = account.UserId, 
      FirstName = "FirstName", 
      LastName = "LastName", 
      Roles = roles 
     }; 

     var userData = JsonConvert.SerializeObject(principalModel); 
     var ticket = new FormsAuthenticationTicket(1, account.UserId, DateTime.Now, DateTime.Now.AddMinutes(30), false, userData); 
     var encryptedTicket = FormsAuthentication.Encrypt(ticket); 
     var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket); 
     Response.Cookies.Add(cookie); 

     SetCulture(account.DefaultCulture); 

     if (!Array.Exists(roles, role => role == "admin" || role == "user")) return UnsuccessfulLoginResult(accountModel.UserName, ErrorMessages.WrongAccountInfo); 

     if (roles.Contains("admin")) { returnUrl = Url.Action("Index", "Admin"); } 
     if (roles.Contains("user")) { returnUrl = Url.Action("Index", "Upload"); } 

     return SuccessfulLoginResult(accountModel.UserName, returnUrl); 
    } 

이 작업은 사용자 /Admin/Index 그렇지 않으면 /Upload/Index 리디렉션합니다. 하지만 사용자가 로그인 한 후 /Admin/Index을 입력하면 인증 필터가 작동하지 않고 사용자가 관리자 페이지에 액세스 할 수 있습니다.

UploadController 및 AdminController에이 속성을 추가했지만이 오류가 발생합니다. 이 문제를 어떻게 해결할 수 있습니까? 이러한 변화와 함께 해결

. . .  

var roles = account.Roles.Select(r => r.RoleName).ToArray(); 

ClaimsIdentity identity = new ClaimsIdentity(DefaultAuthenticationTypes.ApplicationCookie); 

identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, accountModel.UserName)); 

roles.ToList().ForEach((role) => identity.AddClaim(new Claim(ClaimTypes.Role, role))); 

identity.AddClaim(new Claim(ClaimTypes.Name, userCode.ToString())); 

. . . 
+0

사용자 클레임을 어디에 추가합니까? – SeM

답변

0

문제 :

[CustomAuthorize(Roles = "user")] 
public class UploadController : BaseController 

[CustomAuthorize(Roles = "admin")] 
public class AdminController : BaseController 
0

당신은, 사용자에 대한 주장을 추가하려면 방법이 부분을 추가해야합니다. 내 CustomAuthorizeAttribute에서

if (!filterContext.HttpContext.Request.IsAuthenticated) base.OnAuthorization(filterContext); 

이 줄

if (!filterContext.HttpContext.Request.IsAuthenticated) return; 

을 변경 그리고 웹 설정에서 역할을 허용 읽기 라인을 제거했다. 나는이 때 사용자가 아닌 역할에 해당 페이지로 ErrorController 이름과 경로 재 컨트롤러를 추가 한 다음

public class CustomAuthorizeAttribute : AuthorizeAttribute 
{ 
    protected virtual CustomPrincipal CurrentUser => HttpContext.Current.User as CustomPrincipal; 

    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if (!filterContext.HttpContext.Request.IsAuthenticated) base.OnAuthorization(filterContext); 

     if (string.IsNullOrEmpty(Roles)) return; 
     if (CurrentUser == null) return; 
     if (!CurrentUser.IsInRole(Roles)) filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Error", action = "AccessDenied" })); 
    } 
} 

아래 같은 내 속성 최종 버전.

이러한 변경 사항을 통해 나는 /Account/Index에 액세스 할 수없고 [AllowAnonymous] 속성을 아래 작업에 추가했다는 것을 깨달았습니다.

[AllowAnonymous] 
    public ActionResult Index() { return View(); } 

    [HttpPost, ValidateAntiForgeryToken, AllowAnonymous] 
    public ActionResult Index(AccountViewModel accountModel) 
+0

클레임 사용 방법을 모르겠습니다. 폼 기반 인증을 사용했습니다. 클레임 및 양식 인증을 함께 사용할 수 있습니까? –

+0

나는 이것을 추가했지만 작동하지 않는다. –

+0

네, 웹에서' '이 있으면 가능합니다. 구성, 주석 달기. – SeM

관련 문제