The*_*Sky 8 .net c# permissions asp.net-mvc
我不喜欢内置的会员提供商.我决定自己推出.我正试图想出一个在动作级别执行授权的好方法.下面是我的要求试图去了:
ReadWrite拥有权限Read.就像或与enum一样.注意:有些人认为这套要求过于宽泛(见评论).我不这么认为,我认为它们相当简单.
最大的showstopper是属性使用.只能有"常量表达式,typeof表达式或属性参数类型的数组创建表达式".
我想也许有这样的东西让操作具有静态访问权限.在属性内部,它会将int"转换"为实际的Permission或者......:
public static class Operations
{
public static class SectionA
{
public const int Read = 1;
public const int ReadWrite = 2;
}
public static class SectionB
{
// ... and so on...
}
}
Run Code Online (Sandbox Code Playgroud)
但它确实限制了构图.我相信你在想"你为什么不去enum路线?" 好吧,我想计划改变的事情,不想限制为32(int)或64(long)操作,并且必须稍后进行大规模重写(也在db中,这只是丑陋的).
此外,如果有一个比动作/控制器上的属性更好的替代方案,那么我全都倾听建议.
编辑:也是从这篇文章,我读到了关于这个BitArray课程.它似乎有点难看,特别是对于数据库中的任意存储.
首先,我要感谢你吮吸我回答这个问题;)
这是一个很长的答案,只是一个起点.您必须弄清楚如何为用户分配角色以及如何在用户中重新创建角色AuthenticateRequest.
如果这不能回答你的问题,我希望这将是一个灵感.请享用!
装饰控制器动作
我开始在默认情况下装饰这两个动作HomeController:
[AuthorizeRoles(Role.Read)]
public ActionResult Index()
{
ViewData["Message"] = "Welcome to ASP.NET MVC!";
return View();
}
[AuthorizeRoles(Role.Write)]
public ActionResult About()
{
return View();
}
Run Code Online (Sandbox Code Playgroud)
然后,应授予ReadWrite角色中的所有用户访问权限.我在这里选择使用枚举作为魔术字符串的类型安全占位符.这个枚举的作用只不过是占位符.没有复合枚举值,必须在其他地方维护.稍后会详细介绍.
public enum Role
{
Read,
Write,
ReadWrite
}
Run Code Online (Sandbox Code Playgroud)
实现新的授权属性
由于字符串不见了,我需要一个新的authorize属性:
public class AuthorizeRolesAttribute : AuthorizeAttribute
{
private readonly RoleSet authorizedRoles;
public AuthorizeRolesAttribute(params Role[] roles)
{
authorizedRoles = new RoleSet(roles);
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
return authorizedRoles.Includes(httpContext.User);
}
}
Run Code Online (Sandbox Code Playgroud)
所述RoleSet包裹物的一组枚举值,并验证如果IPrincipal是它们中的一个的成员:
public class RoleSet
{
public RoleSet(IEnumerable<Role> roles)
{
Names = roles.Select(role => role.ToString());
}
public bool Includes(IPrincipal user)
{
return Names.Any(user.IsInRole);
}
public bool Includes(string role)
{
return Names.Contains(role);
}
public IEnumerable<string> Names { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)
保持角色
这CompositeRoleSet是注册和处理复合角色的地方.CreateDefault()是所有复合材料都注册的地方.
Resolve()将获取角色列表(枚举值)并将复合材料转换为单个对应项.
public class CompositeRoleSet
{
public static CompositeRoleSet CreateDefault()
{
var set = new CompositeRoleSet();
set.Register(Role.ReadWrite, Role.Read, Role.Write);
return set;
}
private readonly Dictionary<Role, Role[]> compositeRoles = new Dictionary<Role, Role[]>();
private void Register(Role composite, params Role[] contains)
{
compositeRoles.Add(composite, contains);
}
public RoleSet Resolve(params Role[] roles)
{
return new RoleSet(roles.SelectMany(Resolve));
}
private IEnumerable<Role> Resolve(Role role)
{
Role[] roles;
if (compositeRoles.TryGetValue(role, out roles) == false)
{
roles = new[] {role};
}
return roles;
}
}
Run Code Online (Sandbox Code Playgroud)
把它连接起来
我们需要经过身份验证的用户才能使用.我在global.asax中欺骗并硬编码:
public MvcApplication()
{
AuthenticateRequest += OnAuthenticateRequest;
}
private void OnAuthenticateRequest(object sender, EventArgs eventArgs)
{
var allRoles = CompositeRoleSet.CreateDefault();
var roles = allRoles.Resolve(Role.ReadWrite);
Context.User = new ApplicationUser(roles);
}
Run Code Online (Sandbox Code Playgroud)
最后,我们需要IPrincipal了解所有这一切:
public class ApplicationUser : IPrincipal
{
private readonly RoleSet roles;
public ApplicationUser(RoleSet roles)
{
this.roles = roles;
}
public bool IsInRole(string role)
{
return roles.Includes(role);
}
public IIdentity Identity
{
get { return new GenericIdentity("User"); }
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3056 次 |
| 最近记录: |