带有React.js API授权的ASP.NET核心

ovfsdjhp  于 2022-11-26  发布在  .NET
关注(0)|答案(1)|浏览(115)

我正在尝试创建一个具有API授权的ASP.NET Core with React.js项目,但很难找到有意义的文档/说明。
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity-api-authorization?view=aspnetcore-7.0看起来是一个很好的参考,但它使用的是实体框架,而我不是。我的目标是在没有EF的情况下管理用户身份验证。
dotnet new react -au Individual创建的React模板提供了AuthorizeService.jsOidcConfigurationController.cs,我在这里链接了它们:https://gist.github.com/julesx/d3daa6ed5a7f905c984a3fedf02004c0
我的program.cs如下:

using Duende.IdentityServer.Models;
using Microsoft.AspNetCore.Authentication;

var ApiScopes = new List<ApiScope> {
    new ApiScope("api1", "My API")
};

var Clients = new List<Client> {
    new Client {
        ClientId = "client",

        // no interactive user, use the clientid/secret for authentication
        AllowedGrantTypes = GrantTypes.ClientCredentials,

        // secret for authentication
        ClientSecrets =
        {
            new Secret("secret".Sha256())
        },

        // scopes that client has access to
        AllowedScopes = { "api1" }
    }
};

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllersWithViews();

builder.Services.AddIdentityServer()
    .AddDeveloperSigningCredential()
    .AddInMemoryApiScopes(ApiScopes)
    .AddInMemoryClients(Clients);

builder.Services.AddAuthentication()
    .AddIdentityServerJwt();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    // 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.UseIdentityServer();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller}/{action=Index}/{id?}");

app.MapFallbackToFile("index.html");

app.Run();

在努力做到这一点后,应用程序成功启动(开发环境)。
我从前端获取的代码如下:

export async function getKpiData(): Promise<IRawKpi[]> {

    const token = await authService.getAccessToken();

    const response = await fetch('/kpidata', {
        headers: !token ? {} : { 'Authorization': `Bearer ${token}` }
    });

    if (response.status == 200) {
        return response.json();
    }

    return [];
}

这会导致对OidcConfigurationController的get请求失败,并显示以下错误:Unable to resolve service for type 'Microsoft.AspNetCore.ApiAuthorization.IdentityServer.IClientRequestParametersProvider' while attempting to activate 'MyNamespace.Controllers.OidcConfigurationController'.
我知道发生这种情况是因为我没有注册注入到OidcConfigurationController中的IClientRequestParametersProvider,但是当我查看示例代码时,我也没有看到它被注入到那里。我也没有看到任何明显的应该注入到Program.csbuilder.Services中的东西。
我的思路是正确的吗?配置它所需要的“神秘”知识似乎太多了。有没有一个高质量的例子可以参考?Program.cs实现一些超级基本身份验证的最低要求是什么?

dgenwo3n

dgenwo3n1#

IClientRequestParametersProvider已使用对的调用注册

builder.Services.AddIdentityServer()
    .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();

问题是,默认情况下没有“内存中”的用户存储。在这种情况下,客户端是应用程序而不是用户。默认的身份验证模板使用“IdentityServer”,它基于“MS Identity”,而“MS Identity”本身使用EF Core。因此,要使其正常工作,您必须使用EF Core。您可以做的是,使用内存中的数据库来存储用户,而不是使用sqlserver。
若要在csproj中执行此操作,请将“Microsoft.EntityFrameworkCore.SqlServer”的SqlServer包引用替换为“Microsoft.EntityFrameworkCore. Sqllite”。
然后在Program.cs中替换

builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));

var connection = new Microsoft.Data.Sqlite.SqliteConnection(connectionString);
// Open the inmemory database to make sure every instance of DbContext gets the same database all the time
connection.Open();
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(connection));

这确保了数据库总是相同的并且不被重新创建。
在appsettings.json中,对于基于sqlite的内存数据库,将DefaultConnectionString设置为“DataSource=:memory:“(比实际的“InMemory”EF-Core数据源更推荐)。
现在开始将在每次启动时为您提供一个干净的数据库,但在DbContext的不同示例之间保持数据库打开。现在您需要在每次启动时“播种”您想要的用户。为此,您可以在appsettings.json中创建一个条目:

"Users": {
    "test@test.com": "Password1!" 
  },

然后在Program.cs中的var app = builder.Build();下,确保创建了数据库,然后循环这些用户并将其植入数据库,如下所示:

// Create a new service scope for seeding the database
using (var scope = app.Services.CreateScope())
{
    var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
    // Make sure we create the in-memory database first
    await dbContext.Database.EnsureCreatedAsync();
    await dbContext.SaveChangesAsync();

    // Get the usermanager from that scope. UserManager configures MS Identity Users.
    var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();

    // Loop over the key value pairs in the "Users" Section of the appsettings.json
    foreach (var (user, password) in app.Configuration.GetSection("Users").Get<Dictionary<string, string>>())
    {
        // Create the user and make sure the user can log in
        var result = await userManager.CreateAsync(new ApplicationUser()
        {
            UserName = user,
            EmailConfirmed = true
        }, password);

        // Throw if anything goes wrong (e.g. password not safe enough)
        if (!result.Succeeded) throw new Exception(string.Join(", ", result.Errors.Select(x => x.Description)));
    }
}

下面是完整的Program.cs和appsettings.json的要点:https://gist.github.com/WolfspiritM/cf74430e4178cdaea94de5109413e796

相关问题