向IdentityServer4添加自定义身份验证方法

时间:2020-03-09 12:21:13

标签: asp.net-core oauth-2.0 identityserver4 openid openid-connect

我在ASP.NET Core 3上具有IdentityServer4的基本设置-基本上,我们具有简单的注册方法和完整的OAuth 2.0协议。目前,用户可以从/connect/token获取授权令牌,服务器可以使用数据库以某种方式完成整个身份验证过程。

我的问题是-如何自定义身份验证过程?如何授予访问权限,例如,仅授予用户名中带有“ admin”的用户,或者授予仅具有“ p”字母,或出生于68'或仅具有服务器上活动文件夹的密码的用户?

我的Startup.cs代码:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace AuthServer
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<AppUserDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("Default")));

            services.AddIdentity<AppUser, IdentityRole>(
                    options =>
                    {
                        options.Password.RequiredLength = 6;
                        options.Password.RequireLowercase = true;
                        options.Password.RequireDigit = false;
                        options.Password.RequireNonAlphanumeric = false;
                        options.Password.RequireUppercase = false;
                    }
                )
                .AddEntityFrameworkStores<AppUserDbContext>()
                .AddDefaultTokenProviders();


            services.AddIdentityServer()
                .AddInMemoryIdentityResources(Config.Ids)
                .AddInMemoryApiResources(Config.Apis)
                .AddInMemoryClients(Config.Clients)
                .AddDeveloperSigningCredential()
                .AddAspNetIdentity<AppUser>();


            services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
            {
                builder.AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader();
            }));

            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment()) app.UseDeveloperExceptionPage();

            app.UseCors(options => options.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin());
            app.UseIdentityServer();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

1 个答案:

答案 0 :(得分:1)

您可以为此目的实现 IResourceOwnerPasswordValidator 接口。 然后将其注册到您的startup.cs

services.AddIdentityServer()
.AddResourceOwnerValidator<**PasswordAuthentication**>()

有关更多信息,请阅读Resource Owner Password Validation

这是default implementation,因此您可以了解想法并实现自己的想法。

public virtual async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
    {
        var clientId = context.Request?.Client?.ClientId;
        var user = await _userManager.FindByNameAsync(context.UserName);
        if (user != null)
        {
            var result = await _signInManager.CheckPasswordSignInAsync(user, context.Password, true);
            if (result.Succeeded)
            {
                var sub = await _userManager.GetUserIdAsync(user);

                _logger.LogInformation("Credentials validated for username: {username}", context.UserName);
                await _events.RaiseAsync(new UserLoginSuccessEvent(context.UserName, sub, context.UserName, false, clientId));

                context.Result = new GrantValidationResult(sub, AuthenticationMethods.Password);
                return;
            }
            else if (result.IsLockedOut)
            {
                _logger.LogInformation("Authentication failed for username: {username}, reason: locked out", context.UserName);
                await _events.RaiseAsync(new UserLoginFailureEvent(context.UserName, "locked out", false, clientId));
            }
            else if (result.IsNotAllowed)
            {
                _logger.LogInformation("Authentication failed for username: {username}, reason: not allowed", context.UserName);
                await _events.RaiseAsync(new UserLoginFailureEvent(context.UserName, "not allowed", false, clientId));
            }
            else
            {
                _logger.LogInformation("Authentication failed for username: {username}, reason: invalid credentials", context.UserName);
                await _events.RaiseAsync(new UserLoginFailureEvent(context.UserName, "invalid credentials", false, clientId));
            }
        }
        else
        {
            _logger.LogInformation("No user found matching username: {username}", context.UserName);
            await _events.RaiseAsync(new UserLoginFailureEvent(context.UserName, "invalid username", false, clientId));
        }

        context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
    }