【问题标题】:How to use existing DB with IdentityServer4如何将现有数据库与 IdentityServer4 一起使用
【发布时间】:2017-07-12 03:27:40
【问题描述】:

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

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

任何帮助将不胜感激。

谢谢。

【问题讨论】:

    标签: c# identityserver4


    【解决方案1】:

    我从 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 中为依赖注入设置任何对象。

    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 接口和实现,用于验证 OAuth 2.0 资源所有者密码凭据授予(又名密码)。与 GrantTypes.ResourceOwnerPasswordAndClientCredentials 或 GrantTypes.ResourceOwnerPassword 一起使用。

    【讨论】:

    • 非常感谢您的详细回复 :-) 我想知道如何使用 AngularJS 构建注册屏幕或登录屏幕,并且不将用户重定向到 IdentityServer。任何帮助将不胜感激。谢谢。
    • @OBA 这似乎是一个单独的问题。我建议您将其发布到网站上。当您说您不想将用户重定向到 IdentityServer 时,这是否意味着您希望您的应用程序“拥有”登录屏幕的登录屏幕?
    • @OBA 查看here 使用Angular2 的示例项目。您可能希望更加熟悉 IdentityServer4 流程,它允许不同类型的登录流程。
    • 感谢您的回复。我找到了一个 github 项目,它使用资源所有者密码凭证 (ROPC) 身份服务器授予类型来实现我想要的。这是任何有兴趣的人的链接github.com/robisim74/AngularSPAWebAPI谢谢。
    • 请注意,不建议使用该工艺流程,应尽可能避免使用。
    猜你喜欢
    • 2020-11-26
    • 2013-06-27
    • 2019-01-31
    • 1970-01-01
    • 1970-01-01
    • 2016-06-03
    • 1970-01-01
    • 2013-06-11
    • 1970-01-01
    相关资源
    最近更新 更多