Как добавить роли для проверки подлинности Windows в ASP.NET Core
Я создал основной проект asp.net в visual studio 2015 с аутентификацией Windows. Я не могу понять, как добавить роли в личность.
У меня есть таблица с именами пользователей для учетной записи Windows. И когда пользователь открывает веб-сайт, он добавляется в Identity (я полагаю, именно это и происходит, потому что я могу отображать имя пользователя с помощью User.Identity.Name), и я хочу извлечь роли из другой таблицы и назначить их пользователю, Это возможно? Или, может быть, есть лучший способ сделать это? (Почему как?)
Я не смог найти каких-либо конкретных примеров, связанных с аутентификацией Windows, но я прочитал документацию и просмотрел это руководство. И я все еще застрял.
3 ответа
Это рабочий код, который я использую для проверки, находится ли пользователь в роли \ группе, пожалуйста, используйте его на досуге
using System.Collections.Generic;
using System.DirectoryServices.AccountManagement;
using System.Linq;
using System.Security.Principal;
namespace Santander.IsUserInGroupOrRole_cs
{
public class IsUserInRole
{
public static bool IsInGroup(string groupName)
{
var myIdentity = GetUserIdWithDomain();
var myPrincipal = new WindowsPrincipal(myIdentity);
return myPrincipal.IsInRole(groupName);
}
public bool IsInGroup(List<string> groupNames)
{
var myIdentity = GetUserIdWithDomain();
var myPrincipal = new WindowsPrincipal(myIdentity);
return groupNames.Any(group => myPrincipal.IsInRole(group));
}
public static WindowsIdentity GetUserIdWithDomain()
{
var myIdentity = WindowsIdentity.GetCurrent();
return myIdentity;
}
public static string GetUserId()
{
var id = GetUserIdWithDomain().Name.Split('\\');
return id[1];
}
public static string GetUserDisplayName()
{
var id = GetUserIdWithDomain().Name.Split('\\');
var dc = new PrincipalContext(ContextType.Domain, id[0]);
var adUser = UserPrincipal.FindByIdentity(dc, id[1]);
return adUser.DisplayName;
}
}
}
При проверке подлинности Windows роли поступают из Active Directory, а не из базы данных.
Вы можете использовать Преобразование утверждений, чтобы изменить входящую идентификацию при каждом запросе, чтобы извлечь дополнительные роли из вашей базы данных.
public class ClaimsTransformer : IClaimsTransformer
{
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
{
((ClaimsIdentity)principal.Identity).AddClaim(
new Claim("ExampleClaim", "true"));
return Task.FromResult(principal);
}
}
А затем подключите его
app.UseClaimsTransformation(new ClaimsTransformationOptions
{
Transformer = new ClaimsTransformer()
});
Обратите внимание, что в текущем воплощении нет поддержки DI, поэтому вам придется вручную извлекать информацию из вашей базы данных из DI, если она там есть.
Для всех, кто заинтересован, вот простой пример того, как вы можете вставить EF DBContext в пользовательский ClaimsTransformer и добавить некоторые пользовательские утверждения о ролях.
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IClaimsTransformer, MyClaimsTransformer>();
services.AddMvc();
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(
Configuration.GetConnectionString("MyConnStringSetting")
));
(...)
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseClaimsTransformation(context =>
{
var transformer = context.Context.RequestServices.GetRequiredService<IClaimsTransformer>();
return transformer.TransformAsync(context);
});
(...)
}
MyClaimsTransformer.cs
public class MyClaimsTransformer : IClaimsTransformer
{
private readonly MyDbContext _context;
public MyClaimsTransformer(MyDbContext context)
{
_context = context;
}
public Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
{
var identity = (ClaimsIdentity)context.Principal.Identity;
var userName = identity.Name;
var roles = _context.Role.Where(r => r.UserRole.Any(u => u.User.Username == userName)).Select(r => r.Name);
foreach (var role in roles)
{
var claim = new Claim(ClaimTypes.Role, role);
identity.AddClaim(claim);
}
return Task.FromResult(context.Principal);
}
}