我想你现在已经完成了这项工作,但是对于我在学习 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);
}
}
然后我可以在任何控制器上应用 [Authorize(Policy = "Administrator")]
我希望这对你有用。
谢谢。