我只是在我的应用程序中设置了与Identity Framework Core 2.0.1的基本集成。我已根据本文(https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity-primary-key-configuration?tabs=aspnetcore2x)将IdentityUser配置为使用INT而不是STRING作为其主键。
我首先使用代码创建一个通过初始迁移创建的空白数据库。
我遇到的问题是,当我创建一个用户(我使用邮差)时,我得到了以下异常:
Cannot insert explicit value for identity column in table 'AspNetUsers' when IDENTITY_INSERT is set to OFF.
当它传递给UserManager.CreateAsync时我检查了appUser.Id的值,它肯定是= 0(这是Int属性的CLR默认值)
如果我将AppUser配置为使用String作为主键(默认设置),则Id列未设置为标识列,并且我没有收到任何错误 - 创建用户时没有GUID作为ID的问题由Identity框架内部生成。
来自邮递员:
{
"email":"someemail@comcast.net",
"password":"Password123",
"firstName":"Alex",
"lastName":"Florin",
"userName":"aflorin"
}
AppUser.cs
using Microsoft.AspNetCore.Identity;
namespace Driver.Models.Entities
{
public class AppUser : IdentityUser<int>
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
}
AppRole.cs
using Microsoft.AspNetCore.Identity;
namespace Driver.Models.Entities
{
public class AppRole : IdentityRole<int> {
}
}
IAppUserRepository.cs
using System.Threading.Tasks;
namespace Driver.Repositories
{
public interface IAppUserRepository<AppUser>
{
Task Create(AppUser appUser, string password);
}
}
AppUserRepository.cs
using Driver.DBContext;
using Driver.Models.Entities;
using Microsoft.AspNetCore.Identity;
using System.Threading.Tasks;
namespace Driver.Repositories
{
public class AppUserRepository : IAppUserRepository<AppUser>
{
private UserManager<AppUser> _userManager;
protected DriverDbContext _dbContext;
public AppUserRepository(UserManager<AppUser> userManager, DriverDbContext dbContext)
{
_userManager = userManager;
_dbContext = dbContext;
}
public async Task Create(AppUser appUser, string password)
{
var result = await _userManager.CreateAsync(appUser, password);
//ToDo: if (!result.Succeeded) { }
await _dbContext.SaveChangesAsync();
}
}
}
AccountsController.cs
using Driver.Models.Entities;
using Driver.ViewModels.Identity;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Driver.Repositories;
namespace Driver.Controllers
{
[Produces("application/json")]
[Route("api/[controller]")]
public class AccountsController : Controller
{
private IAppUserRepository<AppUser> _appUserRepository;
public AccountsController(UserManager<AppUser> userManager, IAppUserRepository<AppUser> appUserRepository)
{
_appUserRepository = appUserRepository;
}
[HttpPost]
public async Task<IActionResult> Create([FromBody]RegistrationViewModel registrationVM)
{
if (registrationVM == null)
{
return BadRequest();
}
var appUser = Mapper.Map<AppUser>(registrationVM);
await _appUserRepository.Create(appUser, registrationVM.Password);
return CreatedAtAction("Create", new { id = appUser.Id }, Mapper.Map<RegistrationViewModel>(appUser));
}
}
}
RegistrationViewModel.cs
namespace Driver.ViewModels.Identity
{
public class RegistrationViewModel
{
public string Email { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName { get; set; }
}
}
从Startup.cs配置服务
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DriverDbContext>(options => options.UseSqlServer(_config.GetConnectionString("DriverDBConnection")));
services.AddSingleton<IJwtFactory, JwtFactory>();
services.TryAddTransient<IHttpContextAccessor, HttpContextAccessor>();
services.AddIdentity<AppUser, IdentityRole<int>>()
.AddEntityFrameworkStores<DriverDbContext>()
.AddDefaultTokenProviders();
var settings = _config.GetSection("Authentication").Get<AuthenticationAppSettings>();
// Configure JwtIssuerOptions
services.Configure((Models.JwtIssuerOptions options) =>
{
options.Issuer = settings.JwtIssuerOptions.Issuer;
options.Audience = settings.JwtIssuerOptions.Audience;
options.SigningCredentials = new SigningCredentials(_signingKey, SecurityAlgorithms.HmacSha256);
});
// Specify the validation parameters to dictate how we want received tokens validated
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = settings.JwtIssuerOptions.Issuer,
ValidateAudience = true,
ValidAudience = settings.JwtIssuerOptions.Audience,
ValidateIssuerSigningKey = true,
IssuerSigningKey = _signingKey,
RequireExpirationTime = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(configureOptions =>
{
configureOptions.ClaimsIssuer = settings.JwtIssuerOptions.Issuer;
configureOptions.TokenValidationParameters = tokenValidationParameters;
configureOptions.SaveToken = true;
});
// Create an authorization claim policy to guard API controllers and actions
services.AddAuthorization(options =>
{
options.AddPolicy("ApiUser", policy => policy.RequireClaim(Constants.Strings.JwtClaimIdentifiers.Rol, Constants.Strings.JwtClaims.ApiAccess));
});
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = settings.Password.RequiredDigit;
options.Password.RequiredLength = settings.Password.RequiredLength;
options.Password.RequireNonAlphanumeric = settings.Password.RequireNonAlphanumeric;
options.Password.RequireUppercase = settings.Password.RequireUppercase;
options.Password.RequireLowercase = settings.Password.RequireLowercase;
options.Password.RequiredUniqueChars = settings.Password.RequiredUniqueChars;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(settings.Lockout.DefaultLockoutTimeSpan);
options.Lockout.MaxFailedAccessAttempts = settings.Lockout.MaxFailedAccessAttempts;
options.Lockout.AllowedForNewUsers = settings.Lockout.AllowedForNewUsers;
// User settings
options.User.RequireUniqueEmail = settings.User.RequireUniqueEmail;
});
services.AddMvc().AddJsonOptions(
options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
);
services.AddAutoMapper(typeof(Startup));
services.AddScoped<ICompanyRepository, CompanyRepository>();
services.AddScoped<ILookupRepository, LookupRepository>();
services.AddScoped<IManagerRepository, ManagerRepository>();
services.AddScoped<IAppUserRepository<AppUser>, AppUserRepository>();
}
我的DbContext的类声明行(我没有在AppUser实体上进行任何自定义配置):
public class DriverDbContext : IdentityDbContext<AppUser, AppRole, int>