如何在没有IdentityServer4的情况下使用ASP.NET Core Identity?

6
我们正在开发一个新的Web应用程序,将托管在我们客户的基础设施中。由于这是一个长期存在且将作为许多未来产品的基础解决方案,我们希望拥有一种未来证明的安全性,即未来的SSO / MFA,但这需要大约3年时间。对于我们的客户来说,依赖某些标准非常重要,因此我考虑使用OpenId。
该解决方案将基于ASP.NET Core + Angular。因此,我发现已经与OpenID Connect兼容的ASP.NET Core Identity,但然后我看到微软推荐Duende Identity Server(IdentityServer4)here
问题在于,我们是一个小团队,正在构建一个小应用程序,但在一个大型企业中,因此必须选择授权版本。另一个问题是,由于是我们的客户自行部署应用程序,因此我们无法控制部署的服务器数量,因此我们必须选择“企业”订阅,这完全超出了我们的预算。
尽管如此,我们仍希望能够使用ASP.NET Core Identity连接到不同的用户源,管理应用程序的权限,并在控制器上使用属性。那么,如何在不使用IdentityServer的情况下使用ASP.NET Core Identity呢?

使用PHP代替。然而,我认为OpenIddict仍然是开源的Apache许可证,因此是一个可行的选择。 - Pieterjan
使用本地账户是否是一个选项?这样你可以将用户数据存储在自己的数据库中。 - MaartenDev
本地账户是指什么?解决方案将部署在Docker组件中,因此我们必须能够备份它们。所以,如果您在谈论本地数据库,那么如何实现备份呢? - J4N
顺便说一下,大多数企业不使用与IdentityServer相关的任何内容,而是选择使用Azure ActiveDirectory。据我所知,它更加灵活易配置。 - Pieterjan
@Pieterjan 我很希望能够这样做,但是我们的大多数客户都在私有网络上运行此应用,并没有互联网访问权限,我不确定 Azure Active Directory 是否能够正常工作? 这个应用程序用于监控关键基础设施(发电厂)。 - J4N
显示剩余2条评论
2个回答

3
根据 MSFT 文档
ASP.NET Core Identity 为 ASP.NET Core Web 应用程序添加了用户界面 (UI) 登录功能。要保护 Web API 和 SPA,请使用以下之一:
- Azure Active Directory Azure - Active Directory B2C (Azure AD B2C) - IdentityServer4
所以他们首先提供了他们的云解决方案。
Identityserver4 免费版本 仍然支持到 .Net Core 3.1 EOL。
作为一个没有预定义 EOL 的免费选项,你可以尝试这个 OpenIddict 示例作为你解决方案的起点,但是它还有一些需要自己填补的空缺。
这里 解释了为什么微软不在他们的文档中提供它(剧透:见上文)。

谢谢您的回答。这是一个关键基础设施监控的解决方案,因此,截至今天,我们的大多数客户不希望将这些网络连接到互联网。我会阅读有关OpenIddict的信息。当您提到“需要填补的差距”时,您是否有任何想法? - J4N
可能我表达不够准确。我提到的“差距”并不是缺乏常见功能,而是需要手动设置所有内容(从协议端点开始)的一般要求,而Idenityserver则提供了大部分实现以及常见设置,只需要在真正需要自定义的地方进行覆盖即可。 - d_f

2

您可以使用纯 ASP.NET Core 而不需要 IdentityServer。 如果您在身份验证和 API 上使用相同的后端,则非常容易。

示例(从 source 复制):

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
    o.TokenValidationParameters = new TokenValidationParameters
    {
        ValidIssuer = builder.Configuration["Jwt:Issuer"],
        ValidAudience = builder.Configuration["Jwt:Audience"],
        IssuerSigningKey = new SymmetricSecurityKey
            (Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])),
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = false,
        ValidateIssuerSigningKey = true
    };
});
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseHttpsRedirection();
app.MapGet("/security/getMessage", () => "Hello World!").RequireAuthorization();
app.MapPost("/security/createToken",
[AllowAnonymous] (User user) =>
{
    if (user.UserName == "joydip" && user.Password == "joydip123")
    {
        var issuer = builder.Configuration["Jwt:Issuer"];
        var audience = builder.Configuration["Jwt:Audience"];
        var key = Encoding.ASCII.GetBytes
        (builder.Configuration["Jwt:Key"]);
        var tokenDescriptor = new SecurityTokenDescriptor
        {
            Subject = new ClaimsIdentity(new[]
            {
                new Claim("Id", Guid.NewGuid().ToString()),
                new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
                new Claim(JwtRegisteredClaimNames.Email, user.UserName),
                new Claim(JwtRegisteredClaimNames.Jti,
                Guid.NewGuid().ToString())
             }),
            Expires = DateTime.UtcNow.AddMinutes(5),
            Issuer = issuer,
            Audience = audience,
            SigningCredentials = new SigningCredentials
            (new SymmetricSecurityKey(key),
            SecurityAlgorithms.HmacSha512Signature)
        };
        var tokenHandler = new JwtSecurityTokenHandler();
        var token = tokenHandler.CreateToken(tokenDescriptor);
        var jwtToken = tokenHandler.WriteToken(token);
        var stringToken = tokenHandler.WriteToken(token);
        return Results.Ok(stringToken);
    }
    return Results.Unauthorized();
});
app.UseAuthentication();
app.UseAuthorization();
app.Run();

另请参阅:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接