Как использовать существующую БД с IdentityServer4

Я хочу использовать IdentityServer4 со своей собственной базой данных. У меня есть отдельные таблицы для администратора и студентов, и обе сущности имеют отдельные права.

Я хочу знать, как настроить базу данных IdentityServer EF для работы с моей существующей БД?

Любая помощь будет высоко оценена.

Спасибо.


person Obaid    schedule 22.02.2017    source источник


Ответы (1)


Я начал с IdentityServer4 пример быстрого запуска 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...
}

Во-вторых, я использовал объект UserManager из AccountController в образце.

private readonly UserManager _userManager;

public AccountController(
        IIdentityServerInteractionService interaction,
        IClientStore clientStore,
        IHttpContextAccessor httpContextAccessor,
        UserManager userManager
        )
{
    _userManager = userManager;
 }

В-третьих, в методе HTTP Post AccountController.Login() я вызвал 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);
}

В-четвертых, я реализовал 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);
    }
}

Наконец, в 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.

person aaronR    schedule 22.02.2017
comment
Большое спасибо за ваш подробный ответ :-) Я хотел знать, как я могу создать экран регистрации или экран входа в систему с помощью AngularJS и не перенаправлять пользователей на IdentityServer. Любая помощь будет высоко оценена. Спасибо. - person Obaid; 23.02.2017
comment
@OBA Это, кажется, отдельный вопрос. Я бы порекомендовал вам разместить его на сайте. Когда вы говорите, что не хотите перенаправлять пользователей на IdentityServer, означает ли это только экран входа в систему, где вы хотите, чтобы ваше приложение «владело» экраном входа? - person aaronR; 23.02.2017
comment
@OBA Посмотрите здесь пример проекта с использованием Angular2. Вы можете лучше познакомиться с потоками IdentityServer4, которые позволяют использовать различные типы процессов входа. - person aaronR; 23.02.2017
comment
Спасибо за ваш ответ. Я нашел проект github, который использует тип гранта сервера идентификации владельца ресурса (ROPC) для достижения того, что я хотел. Вот ссылка для всех, кто интересуется github.com/robisim74/AngularSPAWebAPI Спасибо. - person Obaid; 24.02.2017
comment
Обратите внимание, что этот процесс не рекомендуется, и его следует избегать, если это вообще возможно. - person aaronR; 24.02.2017