Asp.net mvc 4 覆盖MVC4应用程序的User.IsInRole和[Authorize(Roles=";Admin";)]
我已经为我的MVC4应用程序创建了一个自定义角色提供程序,我已经成功地覆盖了CreateRole、GetAllRoles和RoleExists方法,并将它们链接到我现有的数据库,如下所示:Asp.net mvc 4 覆盖MVC4应用程序的User.IsInRole和[Authorize(Roles=";Admin";)],asp.net-mvc-4,authorization,roleprovider,isinrole,Asp.net Mvc 4,Authorization,Roleprovider,Isinrole,我已经为我的MVC4应用程序创建了一个自定义角色提供程序,我已经成功地覆盖了CreateRole、GetAllRoles和RoleExists方法,并将它们链接到我现有的数据库,如下所示: namespace Project.Providers { public class MyProvider : System.Web.Security.SqlRoleProvider { private MyContext dbcontext = new MyContext(System.Co
namespace Project.Providers
{
public class MyProvider : System.Web.Security.SqlRoleProvider
{
private MyContext dbcontext = new MyContext(System.Configuration.ConfigurationManager.ConnectionStrings["MyContext"].ConnectionString);
private Repository<MyUser> userRepository;
private Repository<Role> roleRepository;
public MyProvider()
{
this.userRepository = new Repository<MyUser>(dbcontext);
this.roleRepository = new Repository<Role>(dbcontext);
}
public override string[] GetAllRoles()
{
IEnumerable<Role> dbRoles = roleRepository.GetAll();
int dbRolesCount = roleRepository.GetAll().Count();
string[] roles = new string[dbRolesCount];
int i = 0;
foreach(var role in dbRoles)
{
roles[i] = role.Name;
i++;
}
return roles;
}
public override bool RoleExists(string roleName)
{
string[] roles = { "Admin", "User", "Business" };
if(roles.Contains(roleName))
return true;
else
return false;
}
public override void CreateRole(string roleName)
{
Role newRole = new Role();
newRole.Name = roleName;
roleRepository.Add(newRole);
roleRepository.SaveChanges();
}
public override bool IsUserInRole(string userName, string roleName)
{
MyUser user = userRepository.Get(u => u.Username == userName).FirstOrDefault();
Role role = roleRepository.Get(r => r.Name == roleName).FirstOrDefault();
if (user.RoleID == role.RoleID)
return true;
else
return false;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.Collections;
using System.Security.Principal;
namespace Project.Data
{
public class MyUser : IPrincipal
{
[Key]
public int UserID { get; set; }
[StringLength(128)]
public string Username { get; set; }
.....other properties
public IIdentity Identity { get; set; }
public bool IsInRole(string role)
{
if (this.Role.Name == role)
{
return true;
}
return false;
}
public IIdentity Identity
{
get { throw new NotImplementedException(); }
}
}
}
我还必须做些什么,以便在使用时:
[Authorize(Roles = "Admin")]
它将基于我设置的角色提供程序,而不是asp默认设置
我的用户类现在如下所示:
namespace Project.Providers
{
public class MyProvider : System.Web.Security.SqlRoleProvider
{
private MyContext dbcontext = new MyContext(System.Configuration.ConfigurationManager.ConnectionStrings["MyContext"].ConnectionString);
private Repository<MyUser> userRepository;
private Repository<Role> roleRepository;
public MyProvider()
{
this.userRepository = new Repository<MyUser>(dbcontext);
this.roleRepository = new Repository<Role>(dbcontext);
}
public override string[] GetAllRoles()
{
IEnumerable<Role> dbRoles = roleRepository.GetAll();
int dbRolesCount = roleRepository.GetAll().Count();
string[] roles = new string[dbRolesCount];
int i = 0;
foreach(var role in dbRoles)
{
roles[i] = role.Name;
i++;
}
return roles;
}
public override bool RoleExists(string roleName)
{
string[] roles = { "Admin", "User", "Business" };
if(roles.Contains(roleName))
return true;
else
return false;
}
public override void CreateRole(string roleName)
{
Role newRole = new Role();
newRole.Name = roleName;
roleRepository.Add(newRole);
roleRepository.SaveChanges();
}
public override bool IsUserInRole(string userName, string roleName)
{
MyUser user = userRepository.Get(u => u.Username == userName).FirstOrDefault();
Role role = roleRepository.Get(r => r.Name == roleName).FirstOrDefault();
if (user.RoleID == role.RoleID)
return true;
else
return false;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.Collections;
using System.Security.Principal;
namespace Project.Data
{
public class MyUser : IPrincipal
{
[Key]
public int UserID { get; set; }
[StringLength(128)]
public string Username { get; set; }
.....other properties
public IIdentity Identity { get; set; }
public bool IsInRole(string role)
{
if (this.Role.Name == role)
{
return true;
}
return false;
}
public IIdentity Identity
{
get { throw new NotImplementedException(); }
}
}
}
我的堆栈跟踪似乎位于以下位置:
System.Web.Security.RolePrincipal.IsInRole(String role)
因此,我尝试以设置自定义提供程序的相同方式实现自定义RolePrincipal。有什么想法吗?不确定它需要什么构造函数参数。以下是我的尝试:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Configuration.Provider;
using Project.Data;
using System.Web.Security;
using System.Security.Principal.IIdentity;
namespace Project.Principal
{
public class MyPrincipal : System.Web.Security.RolePrincipal
{
private MyContext dbcontext = new MyContext(System.Configuration.ConfigurationManager.ConnectionStrings["MyContext"].ConnectionString);
private Repository<MyUser> userRepository;
private Repository<Role> roleRepository;
public MyPrincipal()
{
this.userRepository = new Repository<MyUser>(dbcontext);
this.roleRepository = new Repository<Role>(dbcontext);
}
public override bool IsInRole(string role)
{
//code to be added
return true;
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Web;
使用System.Configuration.Provider;
使用项目数据;
使用System.Web.Security;
使用系统、安全、主体、身份;
名称空间项目.Principal
{
公共类MyPrincipal:System.Web.Security.RolePrincipal
{
私有MyContext dbcontext=newmycontext(System.Configuration.ConfigurationManager.ConnectionStrings[“MyContext”].ConnectionString);
私有存储库用户存储库;
私有存储库角色存储;
公共机构负责人()
{
this.userRepository=新存储库(dbcontext);
this.roleRepository=新存储库(dbcontext);
}
公共覆盖布尔IsInRole(字符串角色)
{
//要添加的代码
返回true;
}
}
}如果在IPrincipal类中重写IsInRole,则EF中的我的类如下所示:
public class MyUser : IPrincipal {
//Properties
...
public bool IsInRole(string role) {
if (Roles.Any(m=>m.NameKey.ToLower().Equals(role.ToLower()))) {
return true;
}
return false;
}
}
然后,一旦您为RoleProvider和MembershipProvider向webconfig添加了适当的部分,您就可以使用Authorize属性了
根据您的评论进行更新
web配置应如下所示:
...
<authentication mode="Forms">
<forms loginUrl="~/Login" timeout="2880"></forms>
</authentication>
<authorization>
</authorization>
..
<membership defaultProvider="MyMembershipProvider">
<providers>
<add name="MyMembershipProvider" type="MyApp.Infrastructure.MyMembershipProvider" connectionStringName="connectionstring" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="true" />
</providers>
</membership>
<roleManager defaultProvider="MyRoleProvider" enabled="true" cacheRolesInCookie="true">
<providers>
<clear />
<add name="MyRoleProvider" type="MyApp.Infrastructure.MyRoleProvider" />
</providers>
</roleManager>
...
用户应具有和IIdentity
在MyUser.cs中:
...
public virtual ICollection<Role> Roles { get; set; }
public IIdentity Identity { get; set; }
。。。
公共虚拟ICollection角色{get;set;}
公共身份标识{get;set;}
从你的评论中,我没有更多的建议来帮助解决问题
更新
我已经通过了一些示例,发现它们在设置我的时很有用:
我在第一次浏览的时候读了很多其他的文章和帖子,但这些都是我费心收藏的东西。我采用了角色/权限方法进行授权,这就是其中一种方法如此的原因。您只需要在自定义角色提供程序中重写方法GetRolesForUser,而不是逻辑性更强的IsUserInRole,因为默认实现会调用它来进行一些不需要的缓存。要解决这个问题,您需要对应用程序进行4次更新
1. Create a class that extends RoleProvider.
namespace MyApp
{
public class MyRoleProvider : RoleProvider
{
public override string ApplicationName
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
public override void CreateRole(string roleName)
{
throw new NotImplementedException();
}
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{
throw new NotImplementedException();
}
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
{
throw new NotImplementedException();
}
public override string[] GetAllRoles()
{
throw new NotImplementedException();
}
public override string[] GetRolesForUser(string username)
{
using (ApplicationDbContext db = new ApplicationDbContext())
{
// get user roles here using user name.
}
}
public override string[] GetUsersInRole(string roleName)
{
throw new NotImplementedException();
}
public override bool IsUserInRole(string username, string roleName)
{
return GetRolesForUser(username).Contains(roleName);
}
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
{
throw new NotImplementedException();
}
public override bool RoleExists(string roleName)
{
throw new NotImplementedException();
}
}
}
2. Create a custom filter that extends AuthorizeAttribute and overwrite its methods.
public class MyAuthFilter : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
var routeValues = new RouteValueDictionary(new
{
controller = "Account",
action = "Login",
});
filterContext.Result = new RedirectToRouteResult(routeValues);
base.HandleUnauthorizedRequest(filterContext);
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
string[] roles = Roles.Split(',');
string userName = HttpContext.Current.User.Identity.Name;
MyRoleProvider myProvider = new MyRoleProvider();
foreach (string role in roles)
{
bool success = myProvider.IsUserInRole(userName, role);
if (success == true)
{
return true;
}
}
return false;
}
3. Configure your custom role provider in your web.config.
<system.web>
<roleManager defaultProvider="MyRoleProvider" enabled="true" cacheRolesInCookie="true">
<providers>
<clear />
<add name="MyRoleProvider" type="MyApp.MyRoleProvider" />
</providers>
</roleManager>
</system.web>
Note: The type here uses the fully qualified namespace and your class name = MyApp.MyRoleProvider. Yours can be different
4. Use your custom filter instead of the default Authorize attribute for your controllers and actions. E.g
[MyAuthFilter]
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Title = "Home Page";
return View();
}
}
1。创建扩展RoleProvider的类。
名称空间MyApp
{
公共类MyRoleProvider:RoleProvider
{
公共重写字符串ApplicationName
{
得到
{
抛出新的NotImplementedException();
}
设置
{
抛出新的NotImplementedException();
}
}
public override void AddUsersToRoles(字符串[]用户名,字符串[]角色名)
{
抛出新的NotImplementedException();
}
公共重写无效CreateRole(字符串roleName)
{
抛出新的NotImplementedException();
}
public override bool DeleteRole(字符串roleName,bool throwOnPopulatedRole)
{
抛出新的NotImplementedException();
}
公共重写字符串[]FindUsersInRole(字符串roleName,字符串usernameToMatch)
{
抛出新的NotImplementedException();
}
公共重写字符串[]GetAllRoles()
{
抛出新的NotImplementedException();
}
公共重写字符串[]GetRolesForUser(字符串用户名)
{
使用(ApplicationDbContext db=new ApplicationDbContext())
{
//在此处使用用户名获取用户角色。
}
}
公共重写字符串[]GetUsersInRole(字符串roleName)
{
抛出新的NotImplementedException();
}
public override bool IsUserInRole(字符串用户名、字符串角色名)
{
返回GetRolesForUser(用户名)。包含(roleName);
}
public override void RemoveUsersFromRoles(字符串[]用户名,字符串[]角色名)
{
抛出新的NotImplementedException();
}
公共覆盖布尔RoleExists(字符串roleName)
{
抛出新的NotImplementedException();
}
}
}
2.创建扩展AuthorizeAttribute并覆盖其方法的自定义筛选器。
公共类MyAuthFilter:AuthorizeAttribute
{
授权时的公共覆盖无效(AuthorizationContext filterContext)
{
基于授权(filterContext);
}
受保护的覆盖无效HandleUnauthorizedRequest(授权上下文筛选器上下文)
{
var routeValues=新的RouteValueDictionary(新的
{
controller=“Account”,
action=“登录”,
});
filterContext.Result=新的RedirectToRouteResult(路由值);
base.HandleUnauthorizedRequest(filterContext);
}
受保护的覆盖bool AuthorizeCore(HttpContextBase httpContext)
{
string[]roles=roles.Split(',');
字符串userName=HttpContext.Current.User.Identity.Name;
MyRoleProvider myProvider=新的MyRoleProvider();
foreach(角色中的字符串角色)
{
布尔