Authentication ASP.Net MVC 6 Windows身份验证自定义授权自定义角色检查来自数据库
我想用ASP.NETMVC6创建一个内部网应用程序 我正在使用windows身份验证,我希望根据数据库表设置不同的规则 例如,如果我想限制某些用户从函数或控制器访问Authentication ASP.Net MVC 6 Windows身份验证自定义授权自定义角色检查来自数据库,authentication,asp.net-core-mvc,Authentication,Asp.net Core Mvc,我想用ASP.NETMVC6创建一个内部网应用程序 我正在使用windows身份验证,我希望根据数据库表设置不同的规则 例如,如果我想限制某些用户从函数或控制器访问 // GET: TestingAuths [Authorize(Roles ="administrator")] public IActionResult Index() { return View(_context.MyTestingAuth.ToList()); } 如何
// GET: TestingAuths
[Authorize(Roles ="administrator")]
public IActionResult Index()
{
return View(_context.MyTestingAuth.ToList());
}
如何检查登录的用户是否具有数据库角色表中的角色管理员。
以下是一个解决方案,但它不适用于ASP.Net MVC 6:
我想要一个ASP.Net MVC 6的解决方案理想情况下,您的身份/身份验证提供商将在声明身份中提供角色声明(如果由您控制) 但是,另一种方法是编写自己的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();
}
}
您应该查看代码中的策略,而不是进行角色检查 需求的处理程序可以在其构造函数中获取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);
}
}
}
公共类MyRoleAuthorizationHandler:AuthorizationHandler
{
IRolesRepository(角色存储);;
公共MyRoleAuthorizationHandler(IRolesRepository rolesRepository)
{
_employeeRepository=employeeRepository;
}
受保护的覆盖无效句柄(AuthorizationContext上下文,
MyRoleRequirement要求)
{
if(_rolesRepository.IsInRole(requirement.Roles,context.User)
{
成功(要求);
}
}
}
然后,您只需在ConfigureServices()中的startup.cs中配置策略和处理程序,并记住在DI系统中注册您的角色存储库,然后就可以了
看起来像
services.AddAuthorization(options =>
{
options.AddPolicy("Administrators", policy =>
{
policy.Requirements.Add(new MyRolesRequirement("Administrator));
});
});
services.AddSingleton<IAuthorizationHandler, MyRolesAuthorizationHandler>();
services.AddAuthorization(选项=>
{
options.AddPolicy(“管理员”,策略=>
{
政策。要求。添加(新的我的角色要求(“管理员”);
});
});
services.AddSingleton();
在文档中按原样显示
请注意,此代码是在输入框中完成的,而不是在VS中完成的,因此可能无法编译:)我想您现在可以使用此代码,但对于我在学习MVC和.Net Core时使用的Intranet,我使用了基于索赔的授权,这取决于针对此人的数据库值 我是这样做的,这无疑是可以改进的,但希望这会及时到来 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?}");
});
}
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);
}
}
public void配置服务(IServiceCollection服务)
{
services.AddMvc(配置=>
{
var policy=new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()文件
.Build();
config.Filters.Add(新的授权过滤器(策略));
})
services.AddAuthorization(选项=>
{
options.AddPolicy(“管理员”,policy=>policy.requirecall(“管理员”);
});
配置(选项=>
{
options.ForwardWindowsAuthentication=true;
});
var连接=等;
services.AddDbContext(options=>options.UseSqlServer(connection));
services.addScope();
}
公共void配置(IApplicationBuilder应用程序、IHostingEnvironment环境、iLogger工厂)
{
AddConsole(this.Configuration.GetSection(“Logging”);
loggerFactory.AddDebug();
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
其他的
{
app.UseExceptionHandler(“/Home/Error”);
}
app.UseSession();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseClaimsTransformation(异步(上下文)=>
{
IClaimsTransformer transformer=context.context.RequestServices.GetRequiredService();
返回wait transformer.TransformAsync(上下文);
});
app.UseStatusCodePages();
app.UseMvc(路由=>
{
routes.MapRoute(
名称:“默认”,
模板:“{controller=Home}/{action=Index}/{id?}”);
});
}
ClaimsTransformer.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?}");
});
}
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);
}
}
public类claimtransformer:IClaimsTransformer
{
私有只读IntranetContext dbcontext;
///
///初始化类的新实例。
///
///也要写。
公共索赔转换程序(IntranetContext上下文)
{
this.dbcontext=context;
}
///
///为经过身份验证的用户管理针对ClaimsPrincipal的索赔
///
///也要写。
///还有待写。
公共异步任务TransformAsync(ClaimTransformationContext)
{
System.Security.Principal.WindowsIdentity WindowsIdentity=null;
foreach(context.Principal.identifies中的var i)
{
if(i.GetType()==typeof(System.Security.Principal.WindowsIdentity))
{
windowsIdentity=(System.Security.Principal.windowsIdentity)i;
}
}
如果(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(新声明(“Id”,Convert.ToString(appUser.Id),ClaimValueTypes.Integer));
((ClaimsIdentity)context.Principal.Identity).AddClaim(新声明(“全名”,appUser.Firstname+“”+appUser.姓氏,ClaimValueTypes.String));
((ClaimsIdentity)context.Principal.Identity).AddClaim(新的Claim(“Firstname”,appUser.Firstname,ClaimValueTypes.String));
((索赔实体)上下文