Мы только начали изучать кодирование и работаем над проектом Asp. Net Core 3.1 Я знаю, что это простая проблема, но я искал везде и не нашел решения.
У нас есть пользовательские модели Admin, Client, Mentor, в которых есть все дополнительные реквизиты, которые нам нужны от пользователя, кроме стандартной электронной почты, Pass, First, Last Name, которые взяты из модели ApplicationUser.
поэтому у нас есть что-то вроде этого (вы можете найти ниже модели):
AdminUserDetails ---\
ClientUserDetails ------ : ApplicationUser : IdentityUser
MentorUserDetails ---/
На данный момент аутентификация и авторизация работает правильно, но все пользователи создаются в таблице AspNetUser в EF, но мы хотим, чтобы каждая роль (например, клиент) создавалась в таблице клиента со всеми свойствами из ApplicationUser и IdentityUser, унаследованными.
Прежде всего, я нашел эту ссылку для наследования моделей от ApplicationUser. Это правильный способ сделать это?
Кроме того, когда пользователь регистрируется с ролью, выбранной в форме, мы хотим назначить этого пользователя соответствующей модели ... UserDetails и получить Identity Id в Guid.
Вот несколько примеров моделей:
public class ApplicationUser : IdentityUser
{
[Required]
[MaxLength(50)]
public string FirstName { get; set; }
[Required]
[MaxLength(50)]
public string LastName { get; set; }
[NotMapped]
public string Name
{
get
{
return FirstName + " " + LastName;
}
}
[Required]
[Display(Name = "Phone Number")]
[DataType(DataType.PhoneNumber)]
public int? PhoneNumber { get; set; }
[Display(Name = "Profile Picture")]
[DataType(DataType.Upload)]
public string? ProfilePicture { get; set; }
}
public class AdministratorDetails : ApplicationUser
{
[Key]
[ForeignKey("ApplicationUser")]
public Guid Id { get; set; }
//Προσθέτω Foreign key se ola ta details APP USER
public virtual ApplicationUser ApplicationUser { get; set; }
}
Запуск:
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.AddCors();
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddRoles<IdentityRole>() //Πρόσθεσα Identity role
.AddRoleManager<RoleManager<IdentityRole>>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddIdentityServerJwt();
services.AddControllersWithViews();
services.AddRazorPages();
// In production, the React files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/build";
});
//SendGrid Confirmation Email Sender
services.AddTransient<IEmailSender, EmailSender>();
services.Configure<AuthMessageSenderOptions>(Configuration);
services.AddTransient<IProfileService, IdentityClaimsProfileService>();
services.AddScoped<IJobCategoriesRepository, JobCategoryRepository>();
services.AddScoped<IMentorRepository, MentorRepository>();
services.AddScoped<IHrDetailsRepository, HrDetailsRepository>();
services.AddScoped<IClientRepository, ClientRepository>();
services.AddScoped<IJobListingsRepository, JobListingsRepository>();
services.AddScoped<IMentorOfferRepository, MentorOfferRepository>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/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.UseCors(
options => options.WithOrigins("https://localhost:5001/")
.AllowAnyHeader()
.AllowAnyMethod()
);
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseRouting();
app.UseIdentityServer();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
app.UseStaticFiles();
app.UseIdentityServer();
CreateRoles(serviceProvider).Wait();
}
private async Task CreateRoles(IServiceProvider serviceProvider)
{
//adding custom roles
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
var UserManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
string[] roleNames = { "Admin", "HR", "Mentor", "Client" };
IdentityResult roleResult;
foreach (var roleName in roleNames)
{
//creating the roles and seeding them to the database
var roleExist = await RoleManager.RoleExistsAsync(roleName);
if (!roleExist)
{
roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
}
}
//creating a super user who could maintain the web app
var powerUser = new ApplicationUser
{
UserName = Configuration.GetSection("UserSettings")["UserEmail"],
Email = Configuration.GetSection("UserSettings")["UserEmail"],
FirstName = "PowerAdmin",
LastName = "Admin",
UserRole = "Admin",
EmailConfirmed = true
};
string UserPassword = Configuration.GetSection("UserSettings")["UserPassword"];
var _user = await UserManager.FindByEmailAsync(Configuration.GetSection("UserSettings")["UserEmail"]);
if (_user == null)
{
var createPowerUser = await UserManager.CreateAsync(powerUser, UserPassword);
if (createPowerUser.Succeeded)
{
//here we tie the new user to the "Admin" role
await UserManager.AddToRoleAsync(powerUser, "Admin");
}
}
}
public class IdentityClaimsProfileService : IProfileService
{
private readonly IUserClaimsPrincipalFactory<ApplicationUser> _claimsFactory;
private readonly UserManager<ApplicationUser> _userManager;
public IdentityClaimsProfileService(UserManager<ApplicationUser> userManager, IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory)
{
_userManager = userManager;
_claimsFactory = claimsFactory;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await _userManager.FindByIdAsync(sub);
var principal = await _claimsFactory.CreateAsync(user);
var roles = await _userManager.GetRolesAsync(user);
var claims = principal.Claims.ToList();
claims = claims.Where(claim => context.RequestedClaimTypes.Contains(claim.Type)).ToList();
foreach(string role in roles)
{
claims.Add(new Claim(JwtClaimTypes.Role, role));
}
context.IssuedClaims = claims;
}
public async Task IsActiveAsync(IsActiveContext context)
{
var sub = context.Subject.GetSubjectId();
var user = await _userManager.FindByIdAsync(sub);
context.IsActive = user != null;
}
}