如何将现有数据库与 IdentityServer4 一起使用
How to use existing DB with IdentityServer4
我想将 IdentityServer4 与我的自定义数据库一起使用。我有单独的管理员和学生表,两个实体都有单独的权利。
我想知道如何配置 IdentityServer EF 数据库以使用我现有的数据库?
非常感谢任何帮助。
谢谢。
我从 IdentityServer4 开始 Quick Start sample 7_JavaScriptClient。
首先,我创建了一个 UserManager class,它可以连接到我的数据源并通过用户名和密码以及 return 该用户对象验证用户。
public class UserManager
{
private SecurityContext _context;
public UserManager(SecurityContext context)
{
_context = context;
}
public Task<User> Find(string username, string password)
{
...Logic to query your custom user table(s)...
}
public Task<List<Claim>> GetClaimsAsync(User user)
{
var claims = new List<Claim>();
//custom database call here to where you store your claims.
var myClaims = ...Your Database call here...
var claimGroupName = "SomeCustomName";
if (security != null && security.Count() > 0)
{
foreach (var claim in security)
{
//Add the value from the field Security_Id from the database to the claim group "SomeCustomName".
claims.Add(new Claim(claimGroupName , claim.SECURITY_ID));
}
}
return Task.FromResult(claims);
}
}
用户对象
public class User
{
public string FIRST_NAME { get; set; }
public string LAST_NAME { get; set; }
public string EMAIL { get; set; }
...Other attributes/properties...
}
其次,我在示例中使用了 AccountController 中的 UserManager 对象。
private readonly UserManager _userManager;
public AccountController(
IIdentityServerInteractionService interaction,
IClientStore clientStore,
IHttpContextAccessor httpContextAccessor,
UserManager userManager
)
{
_userManager = userManager;
}
在 AccountController.Login() HTTP Post 方法中的第三个,我将 UserManager.Find(用户名,密码) 调用给 return 一个用户。
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginInputModel model)
{
// validate username/password
var user = await _userManager.Find(model.Username, model.Password);
//sign the user in with a subject[user_id] and name[web_id]
await HttpContext.Authentication.SignInAsync(user.USER_ID, user.WEB_ID, props);
}
第四,我实现了IProfileService。 [我用这个 article 作为资源。]
public class ProfileService : IProfileService
{
UserManager _myUserManager;
private readonly ILogger<ProfileService> _logger;
public ProfileService(ILogger<ProfileService> logger)
{
_logger = logger;
_myUserManager = new UserManager(new SecurityContext());
}
//Called by IdentityServer Middleware.
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var sub = context.Subject.FindFirst("sub")?.Value;
if (sub != null)
{
var user = await _myUserManager.FindByNameAsync(sub);
//Call custom function to get the claims from the custom database.
var cp = await getClaims(user);
var claims = cp.Claims;
...Optionaly remove any claims that don't need to be sent...
context.IssuedClaims = claims.ToList();
}
}
//Called by IdentityServer Middleware.
public async Task IsActiveAsync(IsActiveContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await _myUserManager.FindByNameAsync(sub);
context.IsActive = user != null;
return;
}
//Custom function to get claims from database via the UserManager.GetClaimsAsync() method.
private async Task<ClaimsPrincipal> getClaims(User user)
{
var id = new ClaimsIdentity();
//set any standard claims
id.AddClaim(new Claim(JwtClaimTypes.PreferredUserName, user.USER_ID));
//get custom claims from database or other source.
id.AddClaims(await _myUserManager.GetClaimsAsync(user));
return new ClaimsPrincipal(id);
}
}
最后,在 Startup.cs 中设置任何用于依赖注入的对象。
public void ConfigureServices(IServiceCollection services)
{
builder.Services.AddTransient<IProfileService, ProfileService>();
//This is the DbContext to our Database where the users and their claims are stored.
services.AddTransient<SecurityContext>();
services.AddTransient<UserManager>();
}
这里也有类似的。
请注意,它们还引用了 IResourceOwnerPasswordValidator 接口和实现,用于验证 OAuth 2.0 资源所有者密码凭证授予(又名密码)。与 GrantTypes.ResourceOwnerPasswordAndClientCredentials 或 GrantTypes.ResourceOwnerPassword 一起使用。
我想将 IdentityServer4 与我的自定义数据库一起使用。我有单独的管理员和学生表,两个实体都有单独的权利。
我想知道如何配置 IdentityServer EF 数据库以使用我现有的数据库?
非常感谢任何帮助。
谢谢。
我从 IdentityServer4 开始 Quick Start sample 7_JavaScriptClient。
首先,我创建了一个 UserManager class,它可以连接到我的数据源并通过用户名和密码以及 return 该用户对象验证用户。
public class UserManager
{
private SecurityContext _context;
public UserManager(SecurityContext context)
{
_context = context;
}
public Task<User> Find(string username, string password)
{
...Logic to query your custom user table(s)...
}
public Task<List<Claim>> GetClaimsAsync(User user)
{
var claims = new List<Claim>();
//custom database call here to where you store your claims.
var myClaims = ...Your Database call here...
var claimGroupName = "SomeCustomName";
if (security != null && security.Count() > 0)
{
foreach (var claim in security)
{
//Add the value from the field Security_Id from the database to the claim group "SomeCustomName".
claims.Add(new Claim(claimGroupName , claim.SECURITY_ID));
}
}
return Task.FromResult(claims);
}
}
用户对象
public class User
{
public string FIRST_NAME { get; set; }
public string LAST_NAME { get; set; }
public string EMAIL { get; set; }
...Other attributes/properties...
}
其次,我在示例中使用了 AccountController 中的 UserManager 对象。
private readonly UserManager _userManager;
public AccountController(
IIdentityServerInteractionService interaction,
IClientStore clientStore,
IHttpContextAccessor httpContextAccessor,
UserManager userManager
)
{
_userManager = userManager;
}
在 AccountController.Login() HTTP Post 方法中的第三个,我将 UserManager.Find(用户名,密码) 调用给 return 一个用户。
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginInputModel model)
{
// validate username/password
var user = await _userManager.Find(model.Username, model.Password);
//sign the user in with a subject[user_id] and name[web_id]
await HttpContext.Authentication.SignInAsync(user.USER_ID, user.WEB_ID, props);
}
第四,我实现了IProfileService。 [我用这个 article 作为资源。]
public class ProfileService : IProfileService
{
UserManager _myUserManager;
private readonly ILogger<ProfileService> _logger;
public ProfileService(ILogger<ProfileService> logger)
{
_logger = logger;
_myUserManager = new UserManager(new SecurityContext());
}
//Called by IdentityServer Middleware.
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var sub = context.Subject.FindFirst("sub")?.Value;
if (sub != null)
{
var user = await _myUserManager.FindByNameAsync(sub);
//Call custom function to get the claims from the custom database.
var cp = await getClaims(user);
var claims = cp.Claims;
...Optionaly remove any claims that don't need to be sent...
context.IssuedClaims = claims.ToList();
}
}
//Called by IdentityServer Middleware.
public async Task IsActiveAsync(IsActiveContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await _myUserManager.FindByNameAsync(sub);
context.IsActive = user != null;
return;
}
//Custom function to get claims from database via the UserManager.GetClaimsAsync() method.
private async Task<ClaimsPrincipal> getClaims(User user)
{
var id = new ClaimsIdentity();
//set any standard claims
id.AddClaim(new Claim(JwtClaimTypes.PreferredUserName, user.USER_ID));
//get custom claims from database or other source.
id.AddClaims(await _myUserManager.GetClaimsAsync(user));
return new ClaimsPrincipal(id);
}
}
最后,在 Startup.cs 中设置任何用于依赖注入的对象。
public void ConfigureServices(IServiceCollection services)
{
builder.Services.AddTransient<IProfileService, ProfileService>();
//This is the DbContext to our Database where the users and their claims are stored.
services.AddTransient<SecurityContext>();
services.AddTransient<UserManager>();
}
这里也有类似的
请注意,它们还引用了 IResourceOwnerPasswordValidator 接口和实现,用于验证 OAuth 2.0 资源所有者密码凭证授予(又名密码)。与 GrantTypes.ResourceOwnerPasswordAndClientCredentials 或 GrantTypes.ResourceOwnerPassword 一起使用。