我有一个ASP.NET MVC5应用程序,它使用WindowsAuhhentication来验证用户身份。现在我需要为此应用程序添加一个安全层,并希望将其基于标准MVC安全模型并使用AuthorizeAttribute。这依赖于User.IsInRole,但目前这将返回用户所属的组。我不希望将角色存储为AD中的组,而是希望只为每个用户存储在我的数据库中的角色。
所以问题是,我如何覆盖WindowsPrincipal中的IsInRole方法,还是可以创建一个可以满足我想要的CustomPricipal?
我已经找到了很多关于类似主题的信息,但是大多数似乎都参考了MVC4,从我可以收集的内容来看,整个安全模型在MVC4和MVC5之间发生了变化。那么现在最好的方法是什么呢?
非常感谢所有帮助和指示。
干杯迈克
P.S。如果有人知道如何最好地将EF,IOC和缓存融入其中,那么这将是非常好的。
答案 0 :(得分:0)
我发现MVC5 Asp.Identity与旧的会员提供商相比真的是开发人员友好...这可能是目前缺乏文档的原因。它实际上很直观。
如果您的身份验证规则驻留在数据库中,EntityFramework会将存储过程转换为复杂类型。完成后,您可以创建一个“AuthenticationService”服务层,并根据需要使用DI将复杂类型注入Asp.Identity。
要自定义Asp.Net Identity,您只需向IdentityModels.cs和 AccountViewModels.cs 添加属性,默认情况下,Asp.Identity使用您的 ApplicationDbContext 必须完全没有配置。
此外,您可以通过与 User.IsInRole 类似的方式访问用户信息。
答案 1 :(得分:0)
好的,这就是我所做的。我真的希望人们反馈我可以做出的最佳实践和改进。
我创建了一个从WindowsPrincipal派生并使用重写的IsInRole方法的新Principal。
public class QSDPrincipal : WindowsPrincipal
{
private readonly IUserService userService;
public QSDPrincipal(WindowsIdentity ntIdentity,
IUserService userService) :
base(ntIdentity)
{
this.userService = userService;
}
public override bool IsInRole(string role)
{
return userService.CurrentUserIsInRole(role);
}
}
这使用DI来填充生活在我的BL层中的userService对象。所以我必须配置容器来正确构建它。
container.RegisterType<WindowsIdentity>(new HierarchicalLifetimeManager(),
new InjectionFactory(x => (WindowsIdentity)HttpContext.Current.User.Identity));
container.RegisterType<IPrincipal, QSDPrincipal>(new HierarchicalLifetimeManager());
我使用DependencyResolved在PostAuthenticateRequest事件中创建我的新Principal。
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
var newUser = (IPrincipal)DependencyResolver.Current.GetService(typeof(IPrincipal));
HttpContext.Current.User = newUser;
}
然后在UserService本身中,我实现了一个方法并实现了一些简单的缓存,因此它只对每个请求进行一次数据库查询。
public bool CurrentUserIsInRole(string role)
{
return CurrentUserRoles.Contains(role);
}
private IEnumerable<string> currentUserRoles;
public IEnumerable<string> CurrentUserRoles
{
get
{
if (currentUserRoles == null)
{
var user = GetCurrentUser();
currentUserRoles = new List<string>
{
user.Role.Name
};
}
return currentUserRoles;
}
}
就是这样,一切似乎都有效。
非常感谢思想和改进。
干杯迈克