c# - 如何将现有数据库与 IdentityServer4 一起使用

标签 c# identityserver4

我想将 IdentityServer4 与我的自定义数据库一起使用。我为管理员和学生设置了单独的表格,并且两个实体都有单独的权限。

我想知道如何配置 IdentityServer EF 数据库以使用我现有的数据库?

任何帮助将不胜感激。

谢谢。

最佳答案

我从 IdentityServer4 Quick Start sample 7_JavaScriptClient 开始.

首先,我创建了一个 UserManager 类,它可以连接到我的数据源并通过用户名和密码验证用户并返回该用户对象。

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(username, password) 来返回一个用户。
[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 中为依赖注入(inject)设置任何对象。
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>();

 }

这是一个类似的question and anser也是。

请注意,它们还引用了 IResourceOwnerPasswordValidator 接口(interface)和实现,用于验证 OAuth 2.0 资源所有者密码凭据授予(又名密码)。与 GrantTypes.ResourceOwnerPasswordAndClientCredentials 或 GrantTypes.ResourceOwnerPassword 一起使用。

关于c# - 如何将现有数据库与 IdentityServer4 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42385422/

相关文章:

c# - 如何替换表达式的switch语句

c# - 如何使用代码优先方法在 IdentityServer4 的客户端表中添加新列?

identityserver4 - SilentRenewService._tokenExpiring : Error from signinSilent: Frame window timed out t. 错误

c# - 如何序列化具有属性的字符串值列表

asp.net-mvc - 无法找到 IdentityServer4 的 DiscoveryClient

c# - IdentityServer4 直接链接到 Facebook 身份验证

c# - 授权回调端点不断重定向到用户交互登录页面 IdentityServer

c# - webapi 不会使用 $.param 反序列化字符串数组

C# 所有函数和方法抛出异常

c# - c# 的正弦拟合类