创建AuthorizeAttribute - 什么才是我需要知道什么? [英] Creating a AuthorizeAttribute - what do I need to know?

查看:252
本文介绍了创建AuthorizeAttribute - 什么才是我需要知道什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面是我的要求:


  • 我将用户添加到角色的施氮量;在数据库中定义的。

  • I'll be adding users to N amount of roles; defined in a database.

我需要保护每个控制器的动作与我的授权属性。

I need to protect each controller action with my authorize attribute.

例如,Web应用程序会如果登录的用户属于这两种角色,如果他们这样做,我让他们在检查我怎么能告诉授权属性来从一个用户角色数据库表我选择?

For example, the web application would check if the logged in user belongs to either of these two roles and if they do, I let them in. How can I tell the Authorize attribute to fetch the user roles from a database table I choose?

 [Authorize(Roles = "Admin, Technician")]
 public ActionResult Edit(int id)
 {
     return View();
 }

我试过谷歌搜索了很多不同的页面,但没有似乎适合与我所需要的,而且过于复杂。

I've tried Googling for many different pages, but none seem to fit in with what I need and are overly complicated.

如果在 有事我很乐意官方文件找到它为好,因为我没有看到任何东西,我可以使用。

If the official documentation has something I'd love to find it as well, as I didn't see anything I could use.

有什么建议?

例如,这个问题有一个非常干净的寻找答案,但我不知道它是否完整或缺少一些重要的东西。

For example, this question has a very clean looking answer, but I don't know if it's complete or missing something important.

<一个href=\"http://stackoverflow.com/questions/7286379/asp-net-mvc3-role-and-permission-management-with-runtime-permission-assignmen\">ASP.NET MVC3角色和权限管理 - &GT;随着运行权限分配

修改

似乎有什么实际上,我要找的是创建一个自定义角色提供程序,是否正确?难道我的需求的实现这个类,并把它作为我的角色供应商?我相当新的这个,有什么想法?

It seems that what I'm actually looking for is creating a custom role provider, correct? Do I need to implement this class and use it as my Role provider? I'm fairly new at this, any thoughts?

<一个href=\"http://msdn.microsoft.com/en-us/library/8fw7xh74.aspx\">http://msdn.microsoft.com/en-us/library/8fw7xh74.aspx

推荐答案

我已经经历pretty大致相同的情况在过去几周,所以这可能帮助别人在同一条船上其他人。我的方案是在公司内部网上使用存储在Active Directory用户的MVC4应用程序。这使得Windows身份验证提供单点登录,因此无需Forms身份验证。角色都存储在Oracle数据库中。我有3个角色:

I've been going through pretty much the same scenario the past couple of weeks so this might help someone else in the same boat. My scenario is an MVC4 application on a company intranet with users stored in Active Directory. This allows for Windows authentication giving single sign-on so no need for Forms authentication. Roles are stored in an Oracle database. I have 3 roles:


  • 只读:所有用户需要的这个成员来访问应用程序

  • 用户:创建新的类别缩合

  • 管理员:编辑和删除记录

我决定用asp.net角色提供的API来创建自己的AccountRoleProvider。到目前为止,我只需要使用2种方法,在此,GetRolesForUser的isUserInRole和:

I decided to use the asp.net role provider api to create my own AccountRoleProvider. So far I only need to use 2 methods in this, GetRolesForUser and IsUserInRole:

public class AccountRoleProvider : RoleProvider // System.Web.Security.RoleProvider
{
    private readonly IAccountRepository _accountRepository;

    public AccountRoleProvider(IAccountRepository accountRepository)
    {
        this._accountRepository = accountRepository;
    }

    public AccountRoleProvider() : this (new AccountRepository())
    {}

    public override string[] GetRolesForUser(string user521)
    {
        var userRoles = this._accountRepository.GetRoles(user521).ToArray();

        return userRoles;
    }

    public override bool IsUserInRole(string username, string roleName)
    {
        var userRoles = this.GetRolesForUser(username);

        return Utils.IndexOfString(userRoles, roleName) >= 0;
    }
}

我更新web.config中使用我的角色提供:

I updated the web.config to use my role provider:

<authentication mode="Windows" />
<roleManager enabled="true" defaultProvider="AccountRoleProvider">
  <providers>
    <clear/>
    <add name="AccountRoleProvider"
         type="MyApp.Infrastructure.AccountRoleProvider" />
  </providers>
</roleManager>

然后我创建从AuthorizeAttribute,ReadOnlyAuthorize和CustomAuthorize 2自定义属性。

Then I created 2 custom attributes from AuthorizeAttribute, ReadOnlyAuthorize and CustomAuthorize.

ReadonlyAuthorize:

ReadonlyAuthorize:

public class ReadonlyAuthorize : AuthorizeAttribute
{
    private IAccountRepository _accountRepository;

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var user = httpContext.User;
        this._accountRepository = new AccountRepository();

        if (!user.Identity.IsAuthenticated)
        {
            return false;
        }

        // Get roles for current user
        var roles = this._accountRepository.GetRoles(user.Identity.Name);

        if (!roles.Contains("readonly"))
        {
            return false;
        }

        return base.AuthorizeCore(httpContext);
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);

        if (filterContext.HttpContext.User.Identity.IsAuthenticated && filterContext.Result is HttpUnauthorizedResult)
        {
            filterContext.Result = new ViewResult { ViewName = "AccessDenied" };
        }
    }
}

CustomAuthorize:

CustomAuthorize:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public string RedirectActionName { get; set; }
    public string RedirectControllerName { get; set; }
    private IAccountRepository _accountRepository;

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var user = httpContext.User;
        this._accountRepository = new AccountRepository();
        var accessAllowed = false;

        // Get the roles passed in with the (Roles = "...") on the attribute
        var allowedRoles = this.Roles.Split(',');

        if (!user.Identity.IsAuthenticated)
        {
            return false;
        }

        // Get roles for current user
        var roles = this._accountRepository.GetRoles(user.Identity.Name);

        foreach (var allowedRole in allowedRoles)
        {
            if (roles.Contains(allowedRole))
            {
                accessAllowed = true;
            }
        }

        if (!accessAllowed)
        {
            return false;
        }

        return base.AuthorizeCore(httpContext);
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        base.OnAuthorization(filterContext);

        if (filterContext.HttpContext.User.Identity.IsAuthenticated && filterContext.Result is HttpUnauthorizedResult)
        {   
            var values = new RouteValueDictionary(new
            {
                action = this.RedirectActionName == string.Empty ? "AccessDenied" : this.RedirectActionName,
                controller = this.RedirectControllerName == string.Empty ? "Home" : this.RedirectControllerName
            });

            filterContext.Result = new RedirectToRouteResult(values);
        }
    }
}

的原因2不同属性的是,我使用一个为所有用户都必须的,以便访问应用一个构件的只读作用。我可以在Global.asax中RegisterGlobalFilters方法,这意味着它会自动应用到每一个控制器补充一点:

The reason for 2 different attributes is that I use one for the Readonly role that all users must be a member of in order to access the app. I can add this in the RegisterGlobalFilters method in Global.asax which means it's applied automatically to every Controller:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
    filters.Add(new ReadonlyAuthorize());
}

然后在CustomAuthorize我可以采取更精细的方法,并指定我想要的角色,并适用于控制器或例如个人行动下面我可以限制访问Delete方法给用户的管理角色:

Then in the CustomAuthorize I can take a more granular approach and specify the roles that I want and apply to a Controller or an individual Action e.g. below I can restrict access to the Delete method to users in the Admin role:

[AccessDeniedAuthorize(RedirectActionName = "AccessDenied", RedirectControllerName = "Home", Roles = "Admin")]
public ActionResult Delete(int id = 0)
{
    var batch = myDBContext.Batches.Find(id);
    if (batch == null)
    {
        return HttpNotFound();
    }

    return View(batch);
}

有进一步的步骤我需要采取诸如与当前用户是其成员的角色更新用户对象。这将检索在我的自定义属性每次用户曾经代替的作用,并且还利用User.IsInRole。像这样的东西应该是可能的Application_AuthenticateRequest在Gloal.asax:

There are further steps I need to take such as updating the User object with the roles the current user is a member of. This will retrieve the roles for the User once instead of every time in my custom attributes, and also utilise User.IsInRole. Something like this should be possible in Application_AuthenticateRequest in Gloal.asax:

var roles = "get roles for this user from respository";

if (Context.User != null)
    Context.User = new GenericPrincipal(Context.User.Identity, roles);

这篇关于创建AuthorizeAttribute - 什么才是我需要知道什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆