【问题标题】:IdentityServer4 with EF6带有 EF6 的 IdentityServer4
【发布时间】:2017-05-17 14:01:57
【问题描述】:

我已经在this 的基础上通过IdentityServer4 实现了基本的Web API 保护。

演示基于内存中的数据。而且大多数教程都是基于用户数据的 EF Core 实现。当我搜索时,IdentityServer3 中有一个 IUserService,现在版本 4 中缺少它。

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

如何从 EF6 存储中检索我的用户数据?

【问题讨论】:

    标签: c# authentication entity-framework-6 authorization identityserver4


    【解决方案1】:

    在 Startup.cs 中,执行此操作

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

    这是ResourceOwnerPasswordValidatorProfileService 的示例

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

    【讨论】:

    • 你能告诉我为什么在调用 `ValidateAsync' 时没有在我的代码中触发 'GetProfileDataAsync' 吗?
    • @MohsenAfsin 不确定,可能在代码到达GetProfileDataAsync之前发生异常?
    • 你能补充一些关于IProfileServiceIResourceOwnerPasswordValidator做什么的解释吗?
    • CustomGrantValidationResult 类从何而来?
    • 请注意 CustomGrantValidationResult 是第 3 版。您需要为第 4 版使用不同的方法
    猜你喜欢
    • 1970-01-01
    • 2014-07-01
    • 2019-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 2019-11-25
    相关资源
    最近更新 更多