2017-02-22 151 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... 
} 

二我用從所述的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。在Startup.cs設置[I用這個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); 
    } 
} 

最後爲依賴注入的任何對象。

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

請注意,它們還引用了用於驗證OAuth 2.0資源所有者密碼憑證授權(aka密碼)的IResourceOwnerPasswordValidator接口和實現。與GrantTypes.ResourceOwnerPasswordAndClientCredentials或GrantTypes.ResourceOwnerPassword一起使用。

+0

非常感謝您的詳細回覆:-)我想知道如何使用AngularJS構建註冊屏幕或登錄屏幕,並且不會將用戶重定向到IdentityServer。任何幫助將不勝感激。 謝謝。 – OBA

+0

@OBA這似乎是一個單獨的問題。我會建議您將該帖子發佈到該網站。當你說你不想將用戶重定向到IdentityServer時,這是否意味着你希望應用程序擁有登錄屏幕的登錄屏幕? – aaronR

+0

@OBA Look [here](https://damienbod.com/2016/10/01/identityserver4-webapi-and-angular2-in-a-single-asp-net-core-project/)爲一個示例項目使用Angular2。您可能希望更熟悉IdentityServer4流程,它允許進行不同類型的登錄。 – aaronR