2

私は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;
    }
}

このカスタム プリンシパルをベース コントローラーで使用します。

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; }
} 

私の routeconfig では、私のデフォルト ルートは/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 にこの属性を追加しましたが、このエラーが発生しています。どうすればこれを修正できますか?

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

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

2 に答える 2

1

ユーザーのクレームを追加する必要があります。この部分をメソッドに追加します。

. . .    

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()));

. . . 
于 2016-10-20T09:57:32.683 に答える
0

これらの変更により問題が解決しました。

私の CustomAuthorizeAttribute でこの行を変更しました

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

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

そして、許可されたロールを Web 構成から読み取った行を削除しました。したがって、以下のような私の属性の最終バージョン

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" })); 
    }
}

次に、ErrorController という名前のコントローラーを追加し、ユーザーがロールにいないときにこのページにリダイレクトしました。

これらの変更により、自分の属性にアクセスできず、以下のアクションに/Account/Index追加されたことに気付きました。[AllowAnonymous]

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

    [HttpPost, ValidateAntiForgeryToken, AllowAnonymous]
    public ActionResult Index(AccountViewModel accountModel)
于 2016-10-20T12:51:51.973 に答える