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

如何将现有数据库与IdentityServer4一起使用,identityserver4,Identityserver4,我想在自定义数据库中使用IdentityServer4。我为管理员和学生提供了单独的表,两个实体都有单独的权限 我想知道如何配置IdentityServer EF数据库以使用现有数据库 任何帮助都将不胜感激 谢谢。我从IdentityServer 4开始 首先,我创建了一个UserManager类,它可以连接到我的数据源,并通过用户名和密码验证用户,然后返回该用户对象 public class UserManager { private SecurityContext _context;

我想在自定义数据库中使用IdentityServer4。我为管理员和学生提供了单独的表,两个实体都有单独的权限

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

任何帮助都将不胜感激


谢谢。

我从IdentityServer 4开始

首先,我创建了一个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);


    }
 }
其次,我在示例中使用了AccountController中的UserManager对象

private readonly UserManager _userManager;

public AccountController(
        IIdentityServerInteractionService interaction,
        IClientStore clientStore,
        IHttpContextAccessor httpContextAccessor,
        UserManager userManager
        )
{
    _userManager = userManager;
 }
在AccountController.Login()HTTP Post方法中,我调用了UserManager.Find(用户名、密码)来返回一个用户

[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);
}
[HttpPost]
[ValidateAntiForgeryToken]
公共异步任务登录(LoginInputModel)
{
//验证用户名/密码
var user=await\u userManager.Find(model.Username,model.Password);
//使用主题[user\u id]和名称[web\u id]登录用户
等待HttpContext.Authentication.SignInAsync(user.user\u ID,user.WEB\u ID,props);
}
第四,我实现了IProfileService。[我将此用作资源。]

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);
    }
}
public类ProfileService:IProfileService
{
UserManager\u myUserManager;
专用只读ILogger\u记录器;
公共档案服务(ILogger记录器)
{
_记录器=记录器;
_myUserManager=new UserManager(new SecurityContext());
}
//由IdentityServer中间件调用。
公共异步任务GetProfileDataAsync(ProfileDataRequestContext上下文)
{
var sub=context.Subject.FindFirst(“sub”)?.Value;
如果(sub!=null)
{
var user=await\u myUserManager.FindByNameAsync(sub);
//调用custom函数从自定义数据库获取索赔。
var cp=等待获取索赔(用户);
var索赔=cp.索赔;
…可选择删除不需要发送的任何索赔。。。
context.IssuedClaims=claims.ToList();
}
}
//由IdentityServer中间件调用。
公共异步任务IsActiveAsync(IsActiveContext上下文)
{
var sub=context.Subject.GetSubjectId();
var user=await\u myUserManager.FindByNameAsync(sub);
context.IsActive=user!=null;
返回;
}
//自定义函数,通过UserManager.GetClaimsAsync()方法从数据库获取索赔。
专用异步任务getClaims(用户)
{
var id=新的ClaimsIdentity();
//设定任何标准索赔
id.AddClaim(新声明(JwtClaimTypes.PreferredUserName,user.user_id));
//从数据库或其他源获取自定义声明。
id.AddClaims(wait_myUserManager.GetClaimsAsync(user));
返回新的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>();

 }
public void配置服务(IServiceCollection服务)
{
builder.Services.AddTransient();
//这是存储用户及其声明的数据库的DbContext。
services.AddTransient();
services.AddTransient();
}
这里还有一个类似的例子


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

非常感谢您的详细回复:-)我想知道如何使用AngularJS构建注册屏幕或登录屏幕,并且不将用户重定向到IdentityServer。我们将非常感谢您的帮助。谢谢。@OBA这似乎是一个单独的问题。我建议你把这个贴到网站上。当您说您不想将用户重定向到IdentityServer时,这是否意味着您只想让您的应用程序“拥有”登录屏幕的登录屏幕?@OBA使用Angular2查找示例项目。您可能希望更熟悉IdentityServer4流,它允许不同类型的登录过程。谢谢您的回复。我发现了一个github项目,它使用资源所有者密码凭据(ROPC)身份服务器授权类型来实现我想要的。这里是任何感兴趣的人的链接,谢谢。请注意,不建议使用该流程,如果可能,应尽量避免使用该流程。
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>();

 }