在 IS4 中实施和验证 Db 用户而不是测试用户的正确方法是什么?
What is the right way for implement and authenticate Db Users in IS4 instead of Test Users?
我正在研究微服务并实现混合流。我的项目在测试用户中运行良好。
但我需要让它更加动态并验证我的数据库用户而不是测试用户。
我在这里分享我的认证项目startup.cs文件代码,我已经试过了:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddControllersWithViews();
services.AddIdentity<User, Role>()
.AddRoles<Role>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
sql => sql.MigrationsAssembly(migrationsAssembly));
})
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
sql => sql.MigrationsAssembly(migrationsAssembly));
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseIdentityServer();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
运行使用上述代码后,我无法登录我的身份验证服务器
控制台上没有显示错误window
浏览器控制台也一样
如果我 运行 下面的代码工作正常并且系统让我登录怎么办
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddTestUsers(Config.TestUsers)
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
sql => sql.MigrationsAssembly(migrationsAssembly));
})
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
sql => sql.MigrationsAssembly(migrationsAssembly));
});
}
我在上面的代码中遗漏了什么?从数据库而不是使用测试用户验证用户的正确方法是什么?
我找到了我的问题答案,但奇怪的是,Identity Server 4 官方文档没有提供任何用于将测试用户切换为实际用户并在 UI 级别进行调整的文档。
答案是:
修改登录页面内容
在Quickstart/Account/AccountController.cs
处可以看到构造函数中注入了TestUser。删除它并注入以下内容:
替换为:
private readonly TestUserStore _users;
有了这个:
private readonly UserManager<User> _userManager;
private readonly SignInManager<User> _signInManager;
在构造函数中,替换如下:
IIdentityServerInteractionService interaction,
IClientStore clientStore,
IAuthenticationSchemeProvider schemeProvider,
IEventService events,
TestUserStore users = null)
{
_users = users ?? new TestUserStore(TestUsers.Users);
_interaction = interaction;
_clientStore = clientStore;
_schemeProvider = schemeProvider;
_events = events;
}
有了这个:
public AccountController(
UserManager<User> userManager,
SignInManager<User> signInManager,
IIdentityServerInteractionService interaction,
IClientStore clientStore,
IAuthenticationSchemeProvider schemeProvider,
IEventService events)
{
_userManager = userManager;
_signInManager = signInManager;
_interaction = interaction;
_clientStore = clientStore;
_schemeProvider = schemeProvider;
_events = events;
}
找到登录post动作,修改登录验证逻辑。
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberLogin, lockoutOnFailure: true);
if (result.Succeeded)
{
var user = await _userManager.FindByNameAsync(model.Username);
await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id.ToString(), user.UserName));
if (context != null)
{
if (await _clientStore.IsPkceClientAsync(context.Client.ClientId))
{
// if the client is PKCE then we assume it's native, so this change in how to
// return the response is for better UX for the end user.
return View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl });
}
// we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
return Redirect(model.ReturnUrl);
}
// request for a local page
if (Url.IsLocalUrl(model.ReturnUrl))
{
return Redirect(model.ReturnUrl);
}
else if (string.IsNullOrEmpty(model.ReturnUrl))
{
return Redirect("~/");
}
else
{
// user might have clicked on a malicious link - should be logged
throw new Exception("invalid return URL");
}
}
await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials"));
ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage);
}
在 Quickstart/Extensions.cs
添加以下代码
public static async Task<bool> IsPkceClientAsync(this IClientStore store, string client_id)
{
if (!string.IsNullOrWhiteSpace(client_id))
{
var client = await store.FindEnabledClientByIdAsync(client_id);
return client?.RequirePkce == true;
}
return false;
}
原始答案与旧的修改:
In Identity Server 4, how to add actual users, not test users
我正在研究微服务并实现混合流。我的项目在测试用户中运行良好。 但我需要让它更加动态并验证我的数据库用户而不是测试用户。
我在这里分享我的认证项目startup.cs文件代码,我已经试过了:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddControllersWithViews();
services.AddIdentity<User, Role>()
.AddRoles<Role>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
sql => sql.MigrationsAssembly(migrationsAssembly));
})
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
sql => sql.MigrationsAssembly(migrationsAssembly));
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseIdentityServer();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
运行使用上述代码后,我无法登录我的身份验证服务器
控制台上没有显示错误window
浏览器控制台也一样
如果我 运行 下面的代码工作正常并且系统让我登录怎么办
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddTestUsers(Config.TestUsers)
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
sql => sql.MigrationsAssembly(migrationsAssembly));
})
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
sql => sql.MigrationsAssembly(migrationsAssembly));
});
}
我在上面的代码中遗漏了什么?从数据库而不是使用测试用户验证用户的正确方法是什么?
我找到了我的问题答案,但奇怪的是,Identity Server 4 官方文档没有提供任何用于将测试用户切换为实际用户并在 UI 级别进行调整的文档。
答案是:
修改登录页面内容
在Quickstart/Account/AccountController.cs
处可以看到构造函数中注入了TestUser。删除它并注入以下内容:
替换为:
private readonly TestUserStore _users;
有了这个:
private readonly UserManager<User> _userManager;
private readonly SignInManager<User> _signInManager;
在构造函数中,替换如下:
IIdentityServerInteractionService interaction,
IClientStore clientStore,
IAuthenticationSchemeProvider schemeProvider,
IEventService events,
TestUserStore users = null)
{
_users = users ?? new TestUserStore(TestUsers.Users);
_interaction = interaction;
_clientStore = clientStore;
_schemeProvider = schemeProvider;
_events = events;
}
有了这个:
public AccountController(
UserManager<User> userManager,
SignInManager<User> signInManager,
IIdentityServerInteractionService interaction,
IClientStore clientStore,
IAuthenticationSchemeProvider schemeProvider,
IEventService events)
{
_userManager = userManager;
_signInManager = signInManager;
_interaction = interaction;
_clientStore = clientStore;
_schemeProvider = schemeProvider;
_events = events;
}
找到登录post动作,修改登录验证逻辑。
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(model.Username, model.Password, model.RememberLogin, lockoutOnFailure: true);
if (result.Succeeded)
{
var user = await _userManager.FindByNameAsync(model.Username);
await _events.RaiseAsync(new UserLoginSuccessEvent(user.UserName, user.Id.ToString(), user.UserName));
if (context != null)
{
if (await _clientStore.IsPkceClientAsync(context.Client.ClientId))
{
// if the client is PKCE then we assume it's native, so this change in how to
// return the response is for better UX for the end user.
return View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl });
}
// we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
return Redirect(model.ReturnUrl);
}
// request for a local page
if (Url.IsLocalUrl(model.ReturnUrl))
{
return Redirect(model.ReturnUrl);
}
else if (string.IsNullOrEmpty(model.ReturnUrl))
{
return Redirect("~/");
}
else
{
// user might have clicked on a malicious link - should be logged
throw new Exception("invalid return URL");
}
}
await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials"));
ModelState.AddModelError(string.Empty, AccountOptions.InvalidCredentialsErrorMessage);
}
在 Quickstart/Extensions.cs
添加以下代码
public static async Task<bool> IsPkceClientAsync(this IClientStore store, string client_id)
{
if (!string.IsNullOrWhiteSpace(client_id))
{
var client = await store.FindEnabledClientByIdAsync(client_id);
return client?.RequirePkce == true;
}
return false;
}
原始答案与旧的修改:
In Identity Server 4, how to add actual users, not test users