在前面我们完成了应用最基础的功能支持以及数据库配置,接下来就是我们的用户角色登录等功能了,在asp.net core中原生Identity可以让我们快速完成这个功能的开发,在.NET8中,asp.net core identity支持了WebApi的注册登录。这让我们在WebApi中可以更爽快的使用。
安装包
首先我们需要安装Microsoft.AspNetCore.Identity.EntityFrameworkCore这个包来创建我们的数据库结构
创建实体
在asp.net core identity中默认包含了IdentityUser,IdentityRole,IdentityRoleClaim,IdentityUserClaim,IdentityUserLogin,IdentityUserRole,IdentityUserToken这几个基类,我们可以直接使用这些,也可以通过继承来灵活扩展我们的表结构。当然,可以按照约定不使用继承的方式,创建类添加必要的属性字段也可。
这里我们选择把所有的类都继承一遍,方便以后扩展。
namespace Wheel.Domain.Identity
{
public class User : IdentityUser, IEntity
{
public virtual DateTimeOffset CreationTime { get; set; }
public virtual ICollection Claims { get; set; }
public virtual ICollection Logins { get; set; }
public virtual ICollection Tokens { get; set; }
public virtual ICollection? UserRoles { get; set; }
}
}
namespace Wheel.Domain.Identity
{
public class Role : IdentityRole, IEntity
{
///
/// 角色类型,0管理台角色,1客户端角色
///
public RoleType RoleType { get; set; }
public Role(string roleName, RoleType roleType) : base (roleName)
{
RoleType = roleType;
}
public Role(string roleName) : base (roleName)
{
}
public Role() : base ()
{
}
public virtual ICollection UserRoles { get; set; }
public virtual ICollection RoleClaims { get; set; }
}
}
这里主要展示一下User和Role,别的可自行查看代码仓库。
修改DbContext
在WheelDbContext继承IdentityDbContext,IdentityDbContext支持传入我们的泛型User,Role类型。
namespace Wheel.EntityFrameworkCore
{
public class WheelDbContext : IdentityDbContext
{
private StoreOptions? GetStoreOptions() => this.GetService()
.Extensions.OfType()
.FirstOrDefault()?.ApplicationServiceProvider
?.GetService>()
?.Value?.Stores;
public WheelDbContext(DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
ConfigureIdentity(builder);
}
void ConfigureIdentity(ModelBuilder builder)
{
var storeOptions = GetStoreOptions();
var maxKeyLength = storeOptions?.MaxLengthForKeys ?? 0;
builder.Ent服务器托管网ity(b =>
{
b.HasKey(u => u.Id);
b.HasIndex(u => u.NormalizedUserName).HasDatabaseName("UserNameIndex").IsUnique();
b.HasIndex(u => u.NormalizedEmail).HasDatabaseName("EmailIndex");
b.ToTable("Users");
b.Property(u => u.ConcurrencyStamp).IsConcurrencyToken();
b.Property(u => u.Id).HasMaxLength(36);
b.Property(u => u.UserName).HasMaxLength(256);
b.Property(u => u.NormalizedUserName).HasMaxLength(256);
b.Property(u => u.Email).HasMaxLength(256);
b.Property(u => u.NormalizedEmail).HasMaxLength(256);
b.Property(u => u.CreationTime).HasDefaultValue(DateTimeOffset.Now);
b.HasMany(e => e.Claims)
.WithOne(e => e.User)
.HasForeignKey(uc => uc.UserId)
.IsRequired();
b.HasMany(e => e.Logins)
.WithOne(e => e.User)
.HasForeignKey(ul => ul.UserId)
.IsRequired();
b.HasMany(e => e.Tokens)
.WithOne(e => e.User)
.HasForeignKey(ut => ut.UserId)
.IsRequired();
b.HasMany(e => e.UserRoles)
.WithOne(e => e.User)
.HasForeignKey(ur => ur.UserId)
.IsRequired();
});
builder.Entity(b =>
{
b.HasKey(uc => uc.Id);
b.ToTable("UserClaims");
});
builder.Entity(b =>
{
b.HasKey(l => new { l.LoginProvider, l.ProviderKey });
if (maxKeyLength > 0)
{
b.Property(l => l.LoginProvider).HasMaxLength(maxKeyLength);
b.Property(l => l.ProviderKey).HasMaxLength(maxKeyLength);
}
b.ToTable("UserLogins");
});
builder.Entity(b =>
{
b.HasKey(t =>服务器托管网 new { t.UserId, t.LoginProvider, t.Name });
if (maxKeyLength > 0)
{
b.Property(t => t.LoginProvider).HasMaxLength(maxKeyLength);
b.Property(t => t.Name).HasMaxLength(maxKeyLength);
}
b.ToTable("UserTokens");
});
builder.Entity(b =>
{
b.HasKey(r => r.Id);
b.HasIndex(r => r.NormalizedName).HasDatabaseName("RoleNameIndex").IsUnique();
b.ToTable("Roles");
b.Property(u => u.Id).HasMaxLength(36);
b.Property(r => r.ConcurrencyStamp).IsConcurrencyToken();
b.Property(u => u.Name).HasMaxLength(256);
b.Property(u => u.NormalizedName).HasMaxLength(256);
b.HasMany(e => e.UserRoles)
.WithOne(e => e.Role)
.HasForeignKey(ur => ur.RoleId)
.IsRequired();
b.HasMany(e => e.RoleClaims)
.WithOne(e => e.Role)
.HasForeignKey(rc => rc.RoleId)
.IsRequired();
});
builder.Entity(b =>
{
b.HasKey(rc => rc.Id);
b.ToTable("RoleClaims");
});
builder.Entity(b =>
{
b.HasKey(r => new { r.UserId, r.RoleId });
b.ToTable("UserRoles");
});
}
}
}
执行数据库迁移命令
接下来我们使用VS的程序包管理器控制台。
使用命令创建和执行迁移文件:
Add-Migration Init
Update-Database
这里也可以使用Dotnet EF命令:
dotnet ef migrations add Init
dotnet ef database update
执行完命令后我们连接数据库即可看到表成功创建。
配置Identity
在Program中添加下面代码:
builder.Services.AddIdentityCore()
.AddRoles()
.AddEntityFrameworkStores()
.AddApiEndpoints();
这里指定了Identity用户类型以及角色类型,并且指定EF操作的DbContext。
AddApiEndpoints则是注入WebAPI所需的服务,我们F12进去可以看到里面的配置。
///
/// Adds configuration and services needed to support
/// but does not configure authentication. Call and/or
/// to configure authentication separately.
///
/// The .
/// The .
public static IdentityBuilder AddApiEndpoints(this IdentityBuilder builder)
{
ArgumentNullException.ThrowIfNull(builder);
builder.AddSignInManager();
builder.AddDefaultTokenProviders();
builder.Services.TryAddTransient();
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton, IdentityEndpointsJsonOptionsSetup>());
return builder;
}
接下来就是配置API了,在中间件中添加MapIdentityApi:
app.MapGroup("api/identity")
.WithTags("Identity")
.MapIdentityApi();
这里需要注意的是,如果不先MapGroup,则我们的请求路径只直接从/开始的,MapGroup(“api/identity”)则是指定从/api/identity开始。WithTags则是指定我们Swagger生成API的Tag显示名称。
下面两图可以看到区别:
直接调用register和login方法即可完成注册登录,这里只贴上一个登录返回的截图,可以看到我们成功拿到了accessToken以及refreshToken。
使用Post带上token请求/api/identity/manage/info。成功拿到用户信息。
这样我们就轻轻松松完成了asp.net core identity对WebApi的集成了。
轮子仓库地址https://github.com/Wheel-Framework/Wheel
欢迎进群催更。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
相关推荐: Hive执行计划之hive依赖及权限查询和常见使用场景
目录 概述 1.explain dependency的查询与使用 2.借助explain dependency解决一些常见问题 2.1.识别看似等价的SQL代码实际上是不等价的: 2.2 通过explain dependency验证将过滤条件在不同位置的查询区…