我想用ASP.Net MVC 6
创建一个Intranet应用程序我正在使用Windows身份验证我希望根据数据库表设置不同的规则
例如,如果我想限制某些用户从函数或控制器访问
// GET: TestingAuths
[Authorize(Roles ="administrator")]
public IActionResult Index()
{
return View(_context.MyTestingAuth.ToList());
}
如何检查登录的用户是否具有我的数据库角色表中的管理员角色。 这是一个解决方案,但它不适用于ASP.Net MVC 6:http://kitsula.com/Article/Custom-Role-Provider-for-MVC
我想要一个ASP.Net MVC 6的解决方案
答案 0 :(得分:1)
我想你现在已经有了这个工作但我正在学习MVC和.Net Core我正在研究Intranet我使用了依赖于针对Person的数据库值的基于声明的授权。
我这样接近它,毫无疑问可以改进,但希望能及时到来。
<强> Startup.cs 强>
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
})
services.AddAuthorization(options =>
{
options.AddPolicy("Administrator", policy => policy.RequireClaim("Administrator"));
});
services.Configure<IISOptions>(options =>
{
options.ForwardWindowsAuthentication = true;
});
var connection = etc etc;
services.AddDbContext<IntranetContext>(options => options.UseSqlServer(connection));
services.AddScoped<IClaimsTransformer, ClaimsTransformer>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(this.Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseSession();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseClaimsTransformation(async (context) =>
{
IClaimsTransformer transformer = context.Context.RequestServices.GetRequiredService<IClaimsTransformer>();
return await transformer.TransformAsync(context);
});
app.UseStatusCodePages();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
<强> ClaimsTransformer.cs 强>
public class ClaimsTransformer : IClaimsTransformer
{
private readonly IntranetContext dbcontext;
/// <summary>
/// Initializes a new instance of the <see cref="ClaimsTransformer" /> class.
/// </summary>
/// <param name="context">Also to be written.</param>
public ClaimsTransformer(IntranetContext context)
{
this.dbcontext = context;
}
/// <summary>
/// Manages claims against the ClaimsPrincipal for Authenticated Users
/// </summary>
/// <param name="context">Also to be written.</param>
/// <returns>Still to be written.</returns>
public async Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
{
System.Security.Principal.WindowsIdentity windowsIdentity = null;
foreach (var i in context.Principal.Identities)
{
if (i.GetType() == typeof(System.Security.Principal.WindowsIdentity))
{
windowsIdentity = (System.Security.Principal.WindowsIdentity)i;
}
}
if (windowsIdentity != null)
{
var username = windowsIdentity.Name.Remove(0, 6);
var appUser = this.dbcontext.Person.FirstOrDefault(m => m.Username == username);
if (appUser != null)
{
((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim("Id", Convert.ToString(appUser.Id), ClaimValueTypes.Integer));
((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim("Fullname", appUser.Firstname + ' ' + appUser.Surname, ClaimValueTypes.String));
((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim("Firstname", appUser.Firstname, ClaimValueTypes.String));
((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim("Surname", appUser.Surname, ClaimValueTypes.String));
if (appUser.Administrator)
{
((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim("Administrator", "1", ClaimValueTypes.Boolean));
}
}
else
{
Person newPerson = new Person();
newPerson.Username = username;
newPerson.Firstname = username.Split('.')[0].ToString().ToTitleCase();
newPerson.Surname = username.Split('.')[1].ToString().ToTitleCase();
newPerson.LocationId = 1;
newPerson.CreatedBy = 1;
newPerson.CreatedDate = DateTime.Now;
newPerson.Email = username + "@mycompany.com";
this.dbcontext.Add(newPerson);
await this.dbcontext.SaveChangesAsync();
appUser = this.dbcontext.Person.FirstOrDefault(m => m.Username == username);
((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim("Id", Convert.ToString(appUser.Id), ClaimValueTypes.Integer));
((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim("Fullname", appUser.Firstname + ' ' + appUser.Surname, ClaimValueTypes.String));
((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim("Firstname", appUser.Firstname, ClaimValueTypes.String));
((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim("Surname", appUser.Surname, ClaimValueTypes.String));
}
}
return await System.Threading.Tasks.Task.FromResult(context.Principal);
}
}
在任何控制器上我都可以申请[授权(政策=“管理员”)]
我希望这适合你。
感谢。
答案 1 :(得分:0)
理想情况下,您的身份/身份验证提供程序会在声明标识中提供角色声明(如果您的控件中有此声明)
但是,另一种方法是编写自己的AuthorizationHandler来拦截mvc调用。
public class CustomAuthorizationRequirement : AuthorizationHandler<CustomAuthorizationRequirement>, IAuthorizationRequirement
{
private readonly AppDBContext _context;
public CustomAuthorizationRequirement(AppDBContext context)
{
_context = context;
}
protected override void Handle(AuthorizationContext context, CustomAuthorizationRequirement requirement)
{
var isValid = false;
//perform any checks you want here i.e. check for authorization filters and validate against your database roles
//Due to the 2 different versions of AuthorizationContext I have hard referenced this
if(context.Resource is Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext)
{
//Get the MVC authorization context
var authContext = (Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext)context.Resource;
//Find the AuthorizeAttribute from the given function
var authAttribute = authContext.Filters.OfType<AuthorizeAttribute>().FirstOrDefault();
foreach(var role in authAttribute.Roles.Split(new char[] {','}))
{
var isInRole = _context.Set<ApplicationUser>().Count(u => u.UserName == context.User.Name && u.UserRoles.Contains(role) > 0);
if (isInRole)
isValid = true;
}
}
if (isValid )
context.Succeed(requirement);
else
context.Fail();
}
}
并注册:
var defaultPolicy = new AuthorizationPolicyBuilder().AddRequirements(new CustomAuthorizationRequirement ()).Build();
var mvcBuilder = services.AddMvcCore(options => options.Filters.Add(new AuthorizeFilter(defaultPolicy)));
答案 2 :(得分:-2)
不要进行角色检查,而应该查看代码中的策略。
需求的处理程序可以在其构造函数中使用DI元素,因此您可以在DI中注册RoleRepository,然后将其置于处理程序构造函数中。然后使用参数化需求来配置策略。
所以,例如;
public class MyRoleRequirement : IAuthorizationRequirement
{
public MyRoleRequirement(string roles)
{
Roles = roles;
}
public string Roles { get; set; }
}
现在,让我们假设您的角色存储库是从IRolesRepository继承而来的,具有IsInRole(字符串角色,ClaimsPrincipal用户)功能。在您的处理程序中,您可以执行类似
的操作public class MyRoleAuthorizationHandler : AuthorizationHandler<MyRoleRequirement>
{
IRolesRepository _rolesRepository;
public MyRoleAuthorizationHandler(IRolesRepository rolesRepository)
{
_employeeRepository = employeeRepository;
}
protected override void Handle(AuthorizationContext context,
MyRoleRequirement requirement)
{
if (_rolesRepository.IsInRole(requirement.Roles, context.User)
{
context.Succeed(requirement);
}
}
}
然后,您只需在ConfigureServices()中的startup.cs中配置策略和处理程序,并记住在DI系统中注册您的角色存储库,然后就可以了。
这可能看起来像
services.AddAuthorization(options =>
{
options.AddPolicy("Administrators", policy =>
{
policy.Requirements.Add(new MyRolesRequirement("Administrator));
});
});
services.AddSingleton<IAuthorizationHandler, MyRolesAuthorizationHandler>();
Code based policies与DI in handlers
一样在文档中请注意,此代码是在输入框而不是VS中完成的,因此可能无法编译:)