2

Ich habe bereits den grundlegenden Web-API-Schutz über IdentityServer4 basierend auf this implementiert.IdentityServer4 mit EF6

Die Demo basiert auf In-Memory-Daten. Und die meisten Tutorials basieren auf der EF Core-Implementierung für Benutzerdaten. Wie ich gesucht gab es ein IUserService in IdentityServer3, die nun in der Version fehlt 4.

builder.AddInMemoryClients(Clients.Get()); 
builder.AddInMemoryScopes(Scopes.Get()); 
builder.AddInMemoryUsers(Users.Get()); 

Wie kann ich meine Benutzerdaten aus einem EF6 Speicher abrufen?

Antwort

4

In Startup.cs, tun dies

builder.Services.AddTransient<IResourceOwnerPasswordValidator, ResourceOwnerPasswordValidator>(); 
builder.Services.AddTransient<IProfileService, ProfileService>(); 

Hier ist ein Beispiel von ResourceOwnerPasswordValidator und ProfileService

public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator 
{ 
    private MyUserManager _myUserService { get; set; } 
    public ResourceOwnerPasswordValidator() 
    { 
     _myUserService = new MyUserManager(); 
    } 

    public async Task<CustomGrantValidationResult> ValidateAsync(string userName, string password, ValidatedTokenRequest request) 
    { 
     var user = await _myUserService.FindByNameAsync(userName); 
     if (user != null && await _myUserService.CheckPasswordAsync(user, password)) 
     { 
      return new CustomGrantValidationResult(user.EmailAddress, "password"); 
     } 
     return new CustomGrantValidationResult("Invalid username or password"); 
    } 
} 


public class ProfileService : IProfileService 
{ 
    MyUserManager _myUserManager; 
    public ProfileService() 
    { 
     _myUserManager = new MyUserManager(); 
    } 

    public async Task GetProfileDataAsync(ProfileDataRequestContext context) 
    { 
     var sub = context.Subject.FindFirst("sub")?.Value; 
     if (sub != null) 
     { 
      var user = await _myUserManager.FindByIdAsync(sub); 
      var cp = await getClaims(user); 

      var claims = cp.Claims; 
      if (context.AllClaimsRequested == false || 
       (context.RequestedClaimTypes != null && context.RequestedClaimTypes.Any())) 
      { 
       claims = claims.Where(x => context.RequestedClaimTypes.Contains(x.Type)).ToArray().AsEnumerable(); 
      } 

      context.IssuedClaims = claims; 
     } 
    } 

    public Task IsActiveAsync(IsActiveContext context) 
    { 
     return Task.FromResult(0); 
    } 

    private async Task<ClaimsPrincipal> getClaims(CustomerSite user) 
    { 
     if (user == null) 
     { 
      throw new ArgumentNullException(nameof(user)); 
     } 
     var userId = await _myUserManager.GetUserIdAsync(user); 
     var userName = await _myUserManager.GetUserNameAsync(user); 
     var id = new ClaimsIdentity(); 
     id.AddClaim(new Claim(JwtClaimTypes.Id, userId)); 
     id.AddClaim(new Claim(JwtClaimTypes.PreferredUserName, userName)); 

     var roles = await _myUserManager.GetRolesAsync(user); 
     foreach (var roleName in roles) 
     { 
      id.AddClaim(new Claim(JwtClaimTypes.Role, roleName));     
     } 

     id.AddClaims(await _myUserManager.GetClaimsAsync(user)); 

     return new ClaimsPrincipal(id); 
    } 
} 
+0

können Sie mir sagen, warum 'GetProfileDataAsync' in meinem Code nicht ausgelöst wird, während 'ValidateAsync‘ wird genannt? –

+0

@MohsenAfsin Nicht sicher, möglicherweise gibt es eine Ausnahme, die geschieht, bevor der Code 'GetProfileDataAsync' erreicht? – sunil

+0

Können Sie bitte eine Erklärung hinzufügen, was "IProfileService" und "IResourceOwnerPasswordValidator" tun? – Shimmy