AuthenticationHandler не запущен - PullRequest
0 голосов
/ 04 мая 2020

Asp. net Core 3.1 MVC

Я пытался настроить вызовы api для своего веб-приложения, использующего идентификационные данные котельной пластины. Когда я вызываю api из приложения windows, получаю html для страницы входа, а ApiAuthenticationHandler.HandleAuthenticateAsyn c () никогда не вызывается. Я не уверен, что мне не хватает. Я не могу найти хороших примеров.

Класс запуска:

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

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {            
        services.AddDbContext<ApplicationDbContext>(options =>
            options.UseSqlServer(
                Configuration.GetConnectionString("DefaultConnection")));
        services.AddAuthentication(options =>
        {
            options.AddScheme<ApiAuthenticationHandler>("API","API");
        });
        services.AddAuthorization(options =>
        { 
            options.FallbackPolicy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
        });

        services.AddDefaultIdentity<IdentityUser>(options => 
        { 
            options.SignIn.RequireConfirmedAccount = true;

            options.Password.RequiredLength = 8;
            options.Password.RequireDigit = true;
            options.Password.RequireNonAlphanumeric = false;
            options.Password.RequireUppercase = false;
            options.Password.RequireLowercase = true;
            options.Password.RequiredUniqueChars = 1;

            options.Lockout.MaxFailedAccessAttempts = 10;
            options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
            options.User.RequireUniqueEmail = true;
        })
        .AddEntityFrameworkStores<ApplicationDbContext>();

        services.AddTransient<IEmailSender, EmailSender>();
        services.Configure<AuthMessageSenderOptions>(Configuration);

        services.AddControllersWithViews(options => {
            options.RespectBrowserAcceptHeader = true;
        }).AddSessionStateTempDataProvider();
        services.AddSession();
        services.AddRazorPages();
        services.Configure<CookiePolicyOptions>(options =>{options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None;});
    }

    // 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.UseDatabaseErrorPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseSession();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });
    }  

ApiAuthenticationHandler:

public class ApiAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
    private readonly UserManager<IdentityUser> _userManager;
    private readonly ApplicationDbContext _context;
    public const string AuthTypeName = "Basic ";
    private const string _authHeaderName = "Authorization";

    public ApiAuthenticationHandler(
        IOptionsMonitor<AuthenticationSchemeOptions> options,
        ILoggerFactory logger,
        UrlEncoder encoder,
        ISystemClock clock,
        UserManager<IdentityUser> userManager,
        ApplicationDbContext context)
        : base(options, logger, encoder, clock)
    {
        _userManager = userManager;
        _context = context;
    }



    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        try
        {
            var authHeader = Request.Headers.Keys.Contains(_authHeaderName) ? (string)Request.Headers[_authHeaderName] : null;
            if (authHeader == null)
            {
                return AuthenticateResult.Fail("Missing Authorization Header");
            }
            string encodedAuth = (authHeader != null && authHeader.StartsWith(AuthTypeName)) ? authHeader.Substring(AuthTypeName.Length).Trim() : null;
            if (string.IsNullOrEmpty(encodedAuth))
            {
                return AuthenticateResult.Fail("Invalid Authorization Header");
            }
            var (username, password) = DecodeUserIdAndPassword(encodedAuth);

            // Authenticate credentials against database
            var founduser = await _context.FetchUser(username);

            if (!await _userManager.CheckPasswordAsync(founduser, password))
            {
                return AuthenticateResult.Fail("Invalid Username or Password");
            }

            // Populate user: adjust claims as needed
            var claims = new[] { new Claim(ClaimTypes.Name, username, ClaimValueTypes.String, AuthTypeName) };
            var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, AuthTypeName));
            var ticket = new AuthenticationTicket(principal, Scheme.Name);
            return AuthenticateResult.Success(ticket);
        }
        catch
        {
            // log and reject
            return AuthenticateResult.Fail("Invalid Authorization Header");
        }
    }
    private static (string userid, string password) DecodeUserIdAndPassword(string encodedAuth)
    {
        var userpass = Encoding.UTF8.GetString(Convert.FromBase64String(encodedAuth));
        var separator = userpass.IndexOf(':');
        if (separator == -1)
            return (null, null);

        return (userpass.Substring(0, separator), userpass.Substring(separator + 1));
    }
}

Контроллер Api

[Route("[Controller]")]
[ApiController]
public class SrcController : ControllerBase
{
    private readonly ApplicationDbContext _context;
    private readonly UserManager<IdentityUser> _userManager;
    public SrcController( UserManager<IdentityUser> userManager, ApplicationDbContext context)
    {
        _context = context;
        _userManager = userManager;
    }
    [HttpGet]
    [Authorize(AuthenticationSchemes ="API")]
    public string ServerTime(string id = null) {
        return DateTime.Now.ToString();
    }

    // POST: Src?...
    [HttpPost]
    public async Task<IActionResult> AddSrcCustomer(string id = null, string name = null, string address = null, string city = null, string state = null, string zip = null, bool? active = null)
    {
        if (string.IsNullOrEmpty(id)) return BadRequest();
        if (string.IsNullOrEmpty(name)) return BadRequest();
        if (string.IsNullOrEmpty(address)) return BadRequest();
        if (!Char.IsDigit(address, 0)) return BadRequest();
        if (string.IsNullOrEmpty(city)) return BadRequest();
        if (string.IsNullOrEmpty(state)) return BadRequest();
        if (string.IsNullOrEmpty(zip)) return BadRequest();
        if (!active.HasValue) return BadRequest();
        var cust = await _context.FetchSingleSrc(UserID,id);
        if (cust == null)
        {
            cust = new SrcCustomer
            {
                User = UserID,
                CustID = id,
                Name = name,
                Address = address,
                City = city,
                State = state,
                Zip = zip,
                Active = active.Value,
                Posted = DateTime.Now,
                ID = Guid.NewGuid()
            };
            _context.SrcCustomer.Add(cust);
        }
        else {
            cust.CustID = id;
            cust.Name = name;
            cust.Address = address;
            cust.City = city;
            cust.State = state;
            cust.Zip = zip;
            cust.Active = active.Value;
            cust.Posted = DateTime.Now;
            _context.Update(cust);
        }
        await _context.SaveChangesAsync();
        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!SrcCustomerExists(cust.ID))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }
        return CreatedAtAction("Src", cust);
    }

    private bool SrcCustomerExists(Guid id)
    {
        return _context.SrcCustomer.Any(e => e.ID == id);
    }
    private Guid UserID { get { return Guid.Parse(_userManager.GetUserId(User)); } }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...