2017-02-22 32 views
2

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

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

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

Спасибо.

ответ

6

Я начал с 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... 
} 

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

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); 
} 

В-четвертых, я реализовал 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 любые объекты для Dependency Injection.

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 (aka password). Используется с GrantTypes.ResourceOwnerPasswordAndClientCredentials или GrantTypes.ResourceOwnerPassword.

+0

Большое спасибо за ваш подробный ответ :-) Я хотел знать, как я могу создать экран регистрации или экран входа в систему с помощью AngularJS и не перенаправлять пользователей на IdentityServer. Любая помощь будет высоко оценена. Спасибо. – OBA

+0

@OBA Это, кажется, отдельный вопрос. Я бы порекомендовал вам опубликовать его на сайте. Когда вы говорите, что не хотите перенаправлять пользователей на IdentityServer, это означает только для экрана входа в систему, где вы хотите, чтобы ваше приложение «имело» экран входа в систему? – aaronR

+0

@OBA Посмотрите [здесь] (https://damienbod.com/2016/10/01/identityserver4-webapi-and-angular2-in-a-single-asp-net-core-project/) для примера проекта, используя Angular2. Возможно, вам захочется ознакомиться с потоками IdentityServer4, которые позволяют использовать различные типы значков в процессах. – aaronR