Добавьте пользовательский метод аутентификации в IdentityServer4 - PullRequest
1 голос
/ 09 марта 2020

У меня есть базовая c настройка IdentityServer4 на ASP. NET Core 3 - в основном, у нас есть простой метод регистрации и реализован весь протокол 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 Ответ

1 голос
/ 09 марта 2020

Для этой цели вы можете реализовать интерфейс IResourceOwnerPasswordValidator . затем зарегистрируйте его в файле startup.cs

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

для получения дополнительной информации прочитайте Проверка пароля владельца ресурса пожалуйста.

Это реализация по умолчанию , так что вы можете получить идею и реализовать свои собственные.

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