zoukankan      html  css  js  c++  java
  • ABP框架使用(版本3.3.1)

    1.IdentityServerClientScopes 分配的Scope太多,会报错

    “Scope parameter exceeds max allowed length”

    在Domain.Shared层改MyAppModuleExtensionConfigurator可以改abp identityserver定义的const值

    private static void ConfigureExistingProperties()
    {
      ClientScopeConsts.ScopeMaxLength = 1000;
    } 

    这表里面字段长度,而Scope parameter validation是identityserver4的包里做的,这样改并没有效果

    应该在Host层改变IdentityServerOptions , PreConfigureServices 和 PostConfigureServices 都可以

    public override void PostConfigureServices(ServiceConfigurationContext context)
            {
                PostConfigure<IdentityServerOptions>(options =>
                {
                    options.InputLengthRestrictions.Scope = 2000;
                });    
            }
    

    2.How to integrate Identity Server with Active Directory #2636
    https://github.com/abpframework/abp/issues/2636

     context.Services.Replace(ServiceDescriptor
         .Transient<UserManager<IdentityUser>, LdapUserManager<IdentityUser>>());
    
    public class LdapUserManager<TUser> : Microsoft.AspNetCore.Identity.UserManager<TUser>
           where TUser : IdentityUser
       {
           private readonly IEventService _events;
           private readonly ILdapManager _ldapManager;
           private readonly AbpLdapOptions _ldapOptions;
    
           public LdapUserManager(
               IUserStore<TUser> store, IOptions<IdentityOptions> optionsAccessor, IPasswordHasher<TUser> passwordHasher,
               IEnumerable<IUserValidator<TUser>> userValidators,
               IEnumerable<IPasswordValidator<TUser>> passwordValidators, ILookupNormalizer keyNormalizer,
               IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<TUser>> logger,
               IEventService events,
               ILdapManager ldapManager,
               IOptions<AbpLdapOptions> ldapOptions
           ) : base(
               store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services,
               logger
           )
           {
               _events = events;
               _ldapManager = ldapManager;
               _ldapOptions = ldapOptions.Value;
           }
    
           public override async Task<bool> CheckPasswordAsync(TUser user, string password)
           {
               if (string.IsNullOrEmpty(_ldapOptions.DomainName))
               {
                   throw new InvalidOperationException("The LDAP Hostname cannot be empty or null.");
               }
    
               if (string.IsNullOrEmpty(password) || string.IsNullOrEmpty(user.UserName))
               {
                   throw new InvalidOperationException("The LDAP User and Password cannot be empty or null.");
               }
    
               var userName = string.IsNullOrWhiteSpace(_ldapOptions.DomainName)
                   ? user.UserName
                   : $"{user.UserName}@{_ldapOptions.DomainName}";
    
               var success = _ldapManager.Authenticate(userName, password);
               if (success)
               {
                   Logger.LogInformation("Credentials validated for username: {username}", userName);
                   await _events.RaiseAsync(new UserLoginSuccessEvent(userName, user.Id.ToString(), userName,
                       interactive: false));
                   return true;
               }
    
               Logger.LogInformation("Authentication failed for username: {username}, reason: invalid credentials",
                   userName);
               await _events.RaiseAsync(new UserLoginFailureEvent(userName, "invalid credentials",
                   interactive: false));
               return false;
           }
    //...
    }

    3. Identity 接口

    IIdentityServerInteractionService:用户交互相关接口

    IResourceStore:获取资源接口:这里包括2中资源 一种是IdentityResource 和 ApiResource

    IClientStore:获取客户端相关接口

    IEventService:事件服务

    UserStoreServices:自定义的用户服务,这里我没有用IdentityServer4的TestUserStore是为了方面自定义处理

    4.证书 参考

    IdentityServer4环境部署失败分析贴(一)

    https://www.cnblogs.com/Imaigne/p/10519493.html

    //在正式环境中,这可能会报错
    builder.AddDeveloperSigningCredential(true, "tempkey.rsa");
    
    //正确方式
    builder.AddSigningCredential(new X509Certificate2(path,
                             Configuration["Certificates:Password"]))
    这里可以参见郭的随笔:
    https://www.cnblogs.com/guolianyu/p/9872661.html        
    

    5.JWT与Reference Token的区别

    IdentityServer4之JWT签名(RSA加密证书)及验签
    https://www.cnblogs.com/guolianyu/p/9872661.html

    6.OIDC

    [认证 & 授权] 4. OIDC(OpenId Connect)身份认证(核心部分)

    https://www.cnblogs.com/linianhui/p/openid-connect-core.html#auto-id-0

    https://github.com/solenovex/Identity-Server-4-Tutorial-Demo-Code

     7.Oauth2.0

    OAuth2.0 知多少

    https://www.cnblogs.com/sheng-jie/p/6564520.html

    8.自定义登录认证,在domain层override IResourceOwnerPasswordValidator 的 ValidateAsync 方法

    用 SignInManager.SignInWithClaimsAsync 可以加 Customer Claims

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Claims;
    using System.Threading.Tasks;
    using IdentityModel;
    using IdentityServer4.AspNetIdentity;
    using IdentityServer4.Events;
    using IdentityServer4.Models;
    using IdentityServer4.Services;
    using IdentityServer4.Validation;
    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Localization;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    using Volo.Abp.DependencyInjection;
    using Volo.Abp.Identity;
    using Volo.Abp.IdentityServer.Localization;
    using Volo.Abp.Security.Claims;
    using Volo.Abp.Uow;
    using Volo.Abp.Validation;
    using IdentityUser = Volo.Abp.Identity.IdentityUser;
    
    namespace Volo.Abp.IdentityServer.AspNetIdentity
    {
        [Dependency(ReplaceServices = true)]
        public class MyAbpResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator, ITransientDependency
        {
            protected SignInManager<IdentityUser> SignInManager { get; }
            protected UserManager<IdentityUser> UserManager { get; }
            protected IdentitySecurityLogManager IdentitySecurityLogManager { get; }
            protected ILogger<ResourceOwnerPasswordValidator<IdentityUser>> Logger { get; }
            protected IStringLocalizer<AbpIdentityServerResource> Localizer { get; }
            protected IHybridServiceScopeFactory ServiceScopeFactory { get; }
            protected AbpIdentityOptions AbpIdentityOptions { get; }
    
            public MyAbpResourceOwnerPasswordValidator(
                UserManager<IdentityUser> userManager,
                SignInManager<IdentityUser> signInManager,
                IdentitySecurityLogManager identitySecurityLogManager,
                ILogger<ResourceOwnerPasswordValidator<IdentityUser>> logger,
                IStringLocalizer<AbpIdentityServerResource> localizer,
                IOptions<AbpIdentityOptions> abpIdentityOptions,
                IHybridServiceScopeFactory serviceScopeFactory)
            {
                UserManager = userManager;
                SignInManager = signInManager;
                IdentitySecurityLogManager = identitySecurityLogManager;
                Logger = logger;
                Localizer = localizer;
                ServiceScopeFactory = serviceScopeFactory;
                AbpIdentityOptions = abpIdentityOptions.Value;
            }
    
            /// <summary>
            /// https://github.com/IdentityServer/IdentityServer4/blob/master/src/AspNetIdentity/src/ResourceOwnerPasswordValidator.cs#L53
            /// </summary>
            /// <param name="context"></param>
            /// <returns></returns>
            [UnitOfWork]
            public virtual async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
            {
                var clientId = context.Request?.Client?.ClientId;
                using var scope = ServiceScopeFactory.CreateScope();
    
                await ReplaceEmailToUsernameOfInputIfNeeds(context);
    
                IdentityUser user = null;
                var additionalClaims = new List<Claim>();
                
    
                async Task SetSuccessResultAsync()
                {
                    var sub = await UserManager.GetUserIdAsync(user);
    
                    Logger.LogInformation("Credentials validated for username: {username}", context.UserName);
    
                    
    
                    await AddCustomClaimsAsync(additionalClaims, user, context);
    
                    await SignInManager.SignInWithClaimsAsync(user, new AuthenticationProperties { IsPersistent = true }, additionalClaims);
    
                    context.Result = new GrantValidationResult(
                        sub,
                        OidcConstants.AuthenticationMethods.Password,
                        additionalClaims.ToArray()
                    );
    
                    await IdentitySecurityLogManager.SaveAsync(
                        new IdentitySecurityLogContext
                        {
                            Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer,
                            Action = IdentityServerSecurityLogActionConsts.LoginSucceeded,
                            UserName = context.UserName,
                            ClientId = clientId
                            
                        }
                    );
                }
              
                if (AbpIdentityOptions.ExternalLoginProviders.Any())
                {
                    foreach (var externalLoginProviderInfo in AbpIdentityOptions.ExternalLoginProviders.Values)
                    {
                        var externalLoginProvider = (IExternalLoginProvider)scope.ServiceProvider
                            .GetRequiredService(externalLoginProviderInfo.Type);
    
                        if (await externalLoginProvider.TryAuthenticateAsync(context.UserName, context.Password))
                        {
                            user = await UserManager.FindByNameAsync(context.UserName);
                            if (user == null)
                            {
                                user = await externalLoginProvider.CreateUserAsync(context.UserName, externalLoginProviderInfo.Name);
                            }
                            else
                            {
                                await externalLoginProvider.UpdateUserAsync(user, externalLoginProviderInfo.Name);
                            }
    
                            await SetSuccessResultAsync();
                            return;
                        }
                    }
                }
    
                user = await UserManager.FindByNameAsync(context.UserName);
                string errorDescription = string.Empty;
                if (user != null)
                {
                    AuthenticationProperties auth = new AuthenticationProperties();
                     var result = await SignInManager.CheckPasswordSignInAsync(user, context.Password, true);
    
                    if (result.Succeeded)
                    {
                        await SetSuccessResultAsync();
                        return;
                    }
                    else if (result.IsLockedOut)
                    {
                        Logger.LogInformation("Authentication failed for username: {username}, reason: locked out", context.UserName);
                        errorDescription = Localizer["UserLockedOut"];
                    }
                    else if (result.IsNotAllowed)
                    {
                        Logger.LogInformation("Authentication failed for username: {username}, reason: not allowed", context.UserName);
                        errorDescription = Localizer["LoginIsNotAllowed"];
                    }
                    else
                    {
                        Logger.LogInformation("Authentication failed for username: {username}, reason: invalid credentials", context.UserName);
                        errorDescription = Localizer["InvalidUserNameOrPassword"];
                    }
    
                    await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext
                    {
                        Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer,
                        Action = result.ToIdentitySecurityLogAction(),
                        UserName = context.UserName,
                        ClientId = clientId
                    });
                    await SetSuccessResultAsync();
                     return;
                }
                else
                {
                    Logger.LogInformation("No user found matching username: {username}", context.UserName);
                    errorDescription = Localizer["InvalidUsername"];
    
                    await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
                    {
                        Identity = IdentityServerSecurityLogIdentityConsts.IdentityServer,
                        Action = IdentityServerSecurityLogActionConsts.LoginInvalidUserName,
                        UserName = context.UserName,
                        ClientId = clientId
                    });
                }
    
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, errorDescription);
            }
    
            protected virtual async Task ReplaceEmailToUsernameOfInputIfNeeds(ResourceOwnerPasswordValidationContext context)
            {
                if (!ValidationHelper.IsValidEmailAddress(context.UserName))
                {
                    return;
                }
    
                var userByUsername = await UserManager.FindByNameAsync(context.UserName);
                if (userByUsername != null)
                {
                    return;
                }
    
                var userByEmail = await UserManager.FindByEmailAsync(context.UserName);
                if (userByEmail == null)
                {
                    return;
                }
    
                context.UserName = userByEmail.UserName;
            }
    
            protected virtual Task AddCustomClaimsAsync(List<Claim> customClaims, IdentityUser user, ResourceOwnerPasswordValidationContext context)
            {
                if (user.TenantId.HasValue)
                {
                    customClaims.Add(new Claim(AbpClaimTypes.TenantId, user.TenantId?.ToString()));
                }
                customClaims.Add(new Claim(AbpClaimTypes.PhoneNumber,"testphone"));
                customClaims.Add(new Claim(JwtClaimTypes.Locale, "testLocale"));
                customClaims.Add(new Claim("testname", "testvalue"));
                return Task.CompletedTask;
            }
        }
    }

    之后在AppService上可以用CurrentUser 获取 Customer Claims

     AbpClaimTypes 可以在 configuration api 获取

    {{baseUrl}}/api/abp/application-configuration

    9. AuthenticationTypes.Federated vs. AuthenticationType Identity.Application

    HttpContext.User.Identity.AuthenticationType == "Identity.Application"
    ClaimsPrincipal principal = new ClaimsPrincipal(new ClaimsIdentity(
                new List<Claim>{
                    new Claim(ClaimTypes.Name, username),
                    new Claim(PartnersUserDataClaim, userData),
                    new Claim(ModuleNameClaim, moduleName)
                },
                "SSO/Windows"));
    
            await HttpContext.Authentication.SignInAsync(APIAuthSchemeName, principal);

    https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/dev/src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs

    然而这种方法我在另一个应用使用却有问题,Claim会被覆盖掉,而 AuthenticationType 是 "AuthenticationTypes.Federation"。

    后来注入了AbpUserClaimsPrincipalFactory,还是不行。
    然后试着在表 IdentityServerApiResources 把 新加的Claim Name加进去,就可以了。

    public static readonly string DefaultAuthenticationType = "AuthenticationTypes.Federation";

    var accessToken = await HttpContext.Authentication.GetTokenAsync("access_token");

    IdentityServer4-masterIdentityServer4srcIdentityServer4srcServicesDefaultDefaultClaimsService.cs

    // Copyright (c) Brock Allen & Dominick Baier. All rights reserved.
    // Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
    
    
    using IdentityModel;
    using IdentityServer4.Extensions;
    using IdentityServer4.Models;
    using IdentityServer4.Validation;
    using Microsoft.Extensions.Logging;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Claims;
    using System.Threading.Tasks;
    
    namespace IdentityServer4.Services
    {
        /// <summary>
        /// Default claims provider implementation
        /// </summary>
        public class DefaultClaimsService : IClaimsService
        {
            /// <summary>
            /// The logger
            /// </summary>
            protected readonly ILogger Logger;
    
            /// <summary>
            /// The user service
            /// </summary>
            protected readonly IProfileService Profile;
    
            /// <summary>
            /// Initializes a new instance of the <see cref="DefaultClaimsService"/> class.
            /// </summary>
            /// <param name="profile">The profile service</param>
            /// <param name="logger">The logger</param>
            public DefaultClaimsService(IProfileService profile, ILogger<DefaultClaimsService> logger)
            {
                Logger = logger;
                Profile = profile;
            }
    
            /// <summary>
            /// Returns claims for an identity token
            /// </summary>
            /// <param name="subject">The subject</param>
            /// <param name="resources">The requested resources</param>
            /// <param name="includeAllIdentityClaims">Specifies if all claims should be included in the token, or if the userinfo endpoint can be used to retrieve them</param>
            /// <param name="request">The raw request</param>
            /// <returns>
            /// Claims for the identity token
            /// </returns>
            public virtual async Task<IEnumerable<Claim>> GetIdentityTokenClaimsAsync(ClaimsPrincipal subject, ResourceValidationResult resources, bool includeAllIdentityClaims, ValidatedRequest request)
            {
                Logger.LogDebug("Getting claims for identity token for subject: {subject} and client: {clientId}",
                    subject.GetSubjectId(),
                    request.Client.ClientId);
    
                var outputClaims = new List<Claim>(GetStandardSubjectClaims(subject));
                outputClaims.AddRange(GetOptionalClaims(subject));
    
                // fetch all identity claims that need to go into the id token
                if (includeAllIdentityClaims || request.Client.AlwaysIncludeUserClaimsInIdToken)
                {
                    var additionalClaimTypes = new List<string>();
    
                    foreach (var identityResource in resources.Resources.IdentityResources)
                    {
                        foreach (var userClaim in identityResource.UserClaims)
                        {
                            additionalClaimTypes.Add(userClaim);
                        }
                    }
    
                    // filter so we don't ask for claim types that we will eventually filter out
                    additionalClaimTypes = FilterRequestedClaimTypes(additionalClaimTypes).ToList();
    
                    var context = new ProfileDataRequestContext(
                        subject,
                        request.Client,
                        IdentityServerConstants.ProfileDataCallers.ClaimsProviderIdentityToken,
                        additionalClaimTypes)
                    {
                        RequestedResources = request.ValidatedResources,
                        ValidatedRequest = request
                    };
    
                    await Profile.GetProfileDataAsync(context);
    
                    var claims = FilterProtocolClaims(context.IssuedClaims);
                    if (claims != null)
                    {
                        outputClaims.AddRange(claims);
                    }
                }
                else
                {
                    Logger.LogDebug("In addition to an id_token, an access_token was requested. No claims other than sub are included in the id_token. To obtain more user claims, either use the user info endpoint or set AlwaysIncludeUserClaimsInIdToken on the client configuration.");
                }
    
                return outputClaims;
            }
    
            /// <summary>
            /// Returns claims for an identity token.
            /// </summary>
            /// <param name="subject">The subject.</param>
            /// <param name="resourceResult">The validated resource result</param>
            /// <param name="request">The raw request.</param>
            /// <returns>
            /// Claims for the access token
            /// </returns>
            public virtual async Task<IEnumerable<Claim>> GetAccessTokenClaimsAsync(ClaimsPrincipal subject, ResourceValidationResult resourceResult, ValidatedRequest request)
            {
                Logger.LogDebug("Getting claims for access token for client: {clientId}", request.Client.ClientId);
    
                var outputClaims = new List<Claim>()
                {
                    new Claim(JwtClaimTypes.ClientId, request.ClientId)
                };
    
                // log if client ID is overwritten
                if (!string.Equals(request.ClientId, request.Client.ClientId))
                {
                    Logger.LogDebug("Client {clientId} is impersonating {impersonatedClientId}", request.Client.ClientId, request.ClientId);
                }
    
                // check for client claims
                if (request.ClientClaims != null && request.ClientClaims.Any())
                {
                    if (subject == null || request.Client.AlwaysSendClientClaims)
                    {
                        foreach (var claim in request.ClientClaims)
                        {
                            var claimType = claim.Type;
    
                            if (request.Client.ClientClaimsPrefix.IsPresent())
                            {
                                claimType = request.Client.ClientClaimsPrefix + claimType;
                            }
    
                            outputClaims.Add(new Claim(claimType, claim.Value, claim.ValueType));
                        }
                    }
                }
    
                // add scopes (filter offline_access)
                // we use the ScopeValues collection rather than the Resources.Scopes because we support dynamic scope values 
                // from the request, so this issues those in the token.
                foreach (var scope in resourceResult.ScopeValues.Where(x => x != IdentityServerConstants.StandardScopes.OfflineAccess))
                {
                    outputClaims.Add(new Claim(JwtClaimTypes.Scope, scope));
                }
    
                // a user is involved
                if (subject != null)
                {
                    if (resourceResult.Resources.OfflineAccess)
                    {
                        outputClaims.Add(new Claim(JwtClaimTypes.Scope, IdentityServerConstants.StandardScopes.OfflineAccess));
                    }
    
                    Logger.LogDebug("Getting claims for access token for subject: {subject}", subject.GetSubjectId());
    
                    outputClaims.AddRange(GetStandardSubjectClaims(subject));
                    outputClaims.AddRange(GetOptionalClaims(subject));
    
                    // fetch all resource claims that need to go into the access token
                    var additionalClaimTypes = new List<string>();
                    foreach (var api in resourceResult.Resources.ApiResources)
                    {
                        // add claims configured on api resource
                        if (api.UserClaims != null)
                        {
                            foreach (var claim in api.UserClaims)
                            {
                                additionalClaimTypes.Add(claim);
                            }
                        }
                    }
    
                    foreach(var scope in resourceResult.Resources.ApiScopes)
                    {
                        // add claims configured on scopes
                        if (scope.UserClaims != null)
                        {
                            foreach (var claim in scope.UserClaims)
                            {
                                additionalClaimTypes.Add(claim);
                            }
                        }
                    }
    
                    // filter so we don't ask for claim types that we will eventually filter out
                    additionalClaimTypes = FilterRequestedClaimTypes(additionalClaimTypes).ToList();
    
                    var context = new ProfileDataRequestContext(
                        subject,
                        request.Client,
                        IdentityServerConstants.ProfileDataCallers.ClaimsProviderAccessToken,
                        additionalClaimTypes.Distinct())
                    {
                        RequestedResources = resourceResult,
                        ValidatedRequest = request
                    };
    
                    await Profile.GetProfileDataAsync(context);
    
                    var claims = FilterProtocolClaims(context.IssuedClaims);
                    if (claims != null)
                    {
                        outputClaims.AddRange(claims);
                    }
                }
    
                return outputClaims;
            }
    
            /// <summary>
            /// Gets the standard subject claims.
            /// </summary>
            /// <param name="subject">The subject.</param>
            /// <returns>A list of standard claims</returns>
            protected virtual IEnumerable<Claim> GetStandardSubjectClaims(ClaimsPrincipal subject)
            {
                var claims = new List<Claim>
                {
                    new Claim(JwtClaimTypes.Subject, subject.GetSubjectId()),
                    new Claim(JwtClaimTypes.AuthenticationTime, subject.GetAuthenticationTimeEpoch().ToString(), ClaimValueTypes.Integer64),
                    new Claim(JwtClaimTypes.IdentityProvider, subject.GetIdentityProvider())
                };
    
                claims.AddRange(subject.GetAuthenticationMethods());
    
                return claims;
            }
    
            /// <summary>
            /// Gets additional (and optional) claims from the cookie or incoming subject.
            /// </summary>
            /// <param name="subject">The subject.</param>
            /// <returns>Additional claims</returns>
            protected virtual IEnumerable<Claim> GetOptionalClaims(ClaimsPrincipal subject)
            {
                var claims = new List<Claim>();
    
                var acr = subject.FindFirst(JwtClaimTypes.AuthenticationContextClassReference);
                if (acr != null) claims.Add(acr);
    
                return claims;
            }
    
            /// <summary>
            /// Filters out protocol claims like amr, nonce etc..
            /// </summary>
            /// <param name="claims">The claims.</param>
            /// <returns></returns>
            protected virtual IEnumerable<Claim> FilterProtocolClaims(IEnumerable<Claim> claims)
            {
                var claimsToFilter = claims.Where(x => Constants.Filters.ClaimsServiceFilterClaimTypes.Contains(x.Type));
                if (claimsToFilter.Any())
                {
                    var types = claimsToFilter.Select(x => x.Type);
                    Logger.LogDebug("Claim types from profile service that were filtered: {claimTypes}", types);
                }
                return claims.Except(claimsToFilter);
            }
    
            /// <summary>
            /// Filters out protocol claims like amr, nonce etc..
            /// </summary>
            /// <param name="claimTypes">The claim types.</param>
            protected virtual IEnumerable<string> FilterRequestedClaimTypes(IEnumerable<string> claimTypes)
            {
                var claimTypesToFilter = claimTypes.Where(x => Constants.Filters.ClaimsServiceFilterClaimTypes.Contains(x));
                return claimTypes.Except(claimTypesToFilter);
            }
        }
    }
    

      

    10.AbpUserClaimsPrincipalFactory

    using System;
    using System.Linq;
    using System.Security.Claims;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.Extensions.Options;
    using Volo.Abp.DependencyInjection;
    using Volo.Abp.Identity;
    using Volo.Abp.Security.Claims;
    using Volo.Abp.Uow;
    using IdentityRole = Volo.Abp.Identity.IdentityRole;
    using IdentityUser = Volo.Abp.Identity.IdentityUser;
    
    namespace DRS.Identity
    {
        [Dependency(ReplaceServices = true)]
        [ExposeServices(typeof(AbpUserClaimsPrincipalFactory))] // 替换旧的AbpUserClaimsPrincipalFactory
        public class MyUserClaimsPrincipalFactory : AbpUserClaimsPrincipalFactory, IScopedDependency
        {
            public MyUserClaimsPrincipalFactory(
                UserManager<IdentityUser> userManager,
                RoleManager<IdentityRole> roleManager,
                IOptions<IdentityOptions> options)
                : base(
                      userManager,
                      roleManager,
                      options)
            {
            }
    
            public override async Task<ClaimsPrincipal> CreateAsync(IdentityUser user)
            {
                var principal = await base.CreateAsync(user);
                var identityPrincipal = principal.Identities.First();
                /// add custom claim
                 identityPrincipal.AddClaim(new Claim("fff", "ddddd"));
    
                return principal;
            }
        }
       
        
    }
    

    11. Permission 分为 Client  和 Role

    GO
    /****** Object:  StoredProcedure [dbo].[AddAPIScope]    Script Date: 2021/1/29 22:53:11 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    
    
    ALTER PROCEDURE [dbo].[AddAPIScope] 
    	@scope  nvarchar(500), 
    	@client  nvarchar(500)='TEST_APP'
    AS
    BEGIN
    
    	-- exec AddAPIScope 'DRS.TEST','TEST_APP'
    	select @scope,@client
    
    	merge into AbpPermissionGrants p
    	using(select newid() as id,null as tenantid,@scope as name,'R' as providername,'admin' as providerkey) as t
    	on(p.name=t.name and p.providername=t.providername and p.providerkey=t.providerkey)
    	when not matched then 
    	insert(id,tenantid,name,providername,providerkey) values(t.id,t.tenantid,t.name,t.providername,t.providerkey);
    	
    
    	merge into AbpPermissionGrants p
    	using(select newid() as id,null as tenantid,@scope as name,'C' as providername,@client as providerkey) as t
    	on(p.name=t.name and p.providername=t.providername and p.providerkey=t.providerkey)
    	when not matched then 
    	insert(id,tenantid,name,providername,providerkey) values(t.id,t.tenantid,t.name,t.providername,t.providerkey);
    
    
    	merge into IdentityServerApiScopes p
    	using(select id as apiresourceid,@scope as name,@scope+' API' as displayname,null as description,0 as required,0 as emphasize,1 as showindiscoverydocument
    	 from [dbo].[IdentityServerApiResources] where name='TEST') as t
    	on(p.apiresourceid =t.apiresourceid and p.name=t.name)
    	when not matched then 
    	insert(apiresourceid,name,displayname,description,required,emphasize,showindiscoverydocument) 
    	values(t.apiresourceid,t.name,t.displayname,t.description,t.required,t.emphasize,t.showindiscoverydocument);
    
    
    	merge into IdentityServerClientScopes p
    	using(select id as clientid,@scope as scope from [dbo].[IdentityServerClients] where ClientId = @client) as t
    	on(p.clientid =t.clientid and p.scope=t.scope)
    	when not matched then 
    	insert(clientid,scope) 
    	values(t.clientid,t.scope);
    
    	select * from [AbpPermissionGrants] where name = @scope
    	select * from [IdentityServerApiScopes] where name = @scope
    	select c.ClientId,cs.* from [IdentityServerClients] c,[IdentityServerClientScopes] cs where c.id=cs.ClientId and scope = @scope
    
    END
    

      

  • 相关阅读:
    认识Cookie和状态管理
    python之requests库使用问题汇总
    如何掌握所有的程序语言--王垠
    非 GUI 模式运行 JMeter 压力测试
    Python 如何将字符串转为字典
    python之operator操作符函数
    python3使用xlrd、xlwt、xlutils、openpyxl、xlsxwriter操作excel
    《敏捷软件测试:测试人员与敏捷团队的实践指南》
    Jmeter跨线程组传递变量
    Jmeter获取当前时间、历史时间、未来时间的方式
  • 原文地址:https://www.cnblogs.com/sui84/p/14123634.html
Copyright © 2011-2022 走看看