所以我在这个问题上已经有一段时间了。
我们有一个web应用程序,它使用IdentityServer4和AspNetIdentity对用户进行身份验证和注册(这是按照预期进行的)。此外,我们还有另一个API (在同一解决方案中),它能够使用IdentityServer4对访问API的用户进行身份验证。
但是,问题是,除了身份验证之外,我们不能使用API来创建新用户。
例如,用户应该能够通过web创建其他用户,而不仅仅是通过web应用程序创建其他用户,因为在我们的示例中,用户被链接到其他用户(将其视为多个概要文件)。
我不太熟悉所有提出.Net核心框架的配置服务,我尝试了多种方式通过API访问web应用程序的用户管理器,通过经典的POST请求注册我的用户,但似乎没有什么效果。在线搜索是很棘手的,因为我们的问题是非常具体的,这就是为什么我在这里张贴。
API Startup.cs - ConfigureServices:
services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
// base-address of your identityserver
options.Authority = Configuration["IdentityServer:Url"];
// name of the API resource
options.ApiName = Configuration["IdentityServer:APIName"];
options.ApiSecret = Configuration["IdentityServer:APISecret"];
options.EnableCaching = true;
options.CacheDuration = TimeSpan.FromMinutes(10); // that's the default
options.RequireHttpsMetadata = Convert.ToBoolean(Configuration["IdentityServer:RequireHttpsMetadata"]);
});API Startup.cs -配置:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors("AllowAllOrigins");
app.UseAuthentication();
app.UseMvc();
}API UsersController.cs -构造器:
private readonly UserManager<ApplicationUser> _userManager;
private readonly ApplicationDbContext _context;
public UsersController(IUserService service,
ApplicationDbContext context,
UserManager<ApplicationUser> userManager)
{
_service = service;
_userManager = userManager;
_context = context;
}现在的问题是,当我启动API并尝试访问UsersController时,会得到以下错误:
System.InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Identity.UserManager`1[XXXXX.Data.Models.ApplicationUser]' while attempting to activate 'XXXXXXX.Api.Controllers.UsersController'.我真诚地希望我至少能找到一些关于如何去做的建议。
如果有什么不清楚的答复,我会非常乐意添加更多的信息或明确的事情。
致以亲切的问候,
马里奥斯。
编辑:感谢您的回复。下面@Vidmantas提供的代码片段完成了这个任务。
由于我对.net核心的了解有限,我在配置服务功能方面做了很多尝试和错误,正如您可以想象的那样,这些功能没有工作。我坚信使用.net内核是一种简单的方法(例如API),但在配置服务时,复杂性(主要是令人费解/令人困惑)急剧增加。
至于架构,您给了我关于未来重构的好主意。记笔记。
马里奥斯。
发布于 2019-02-02 19:21:19
如果我对您的理解是正确的,那么您就不应该通过API来创建用户--这就是为什么您已经设置了Identity Server 4--为您的用户群提供身份验证的中心权限。你真正需要的是:
如果您使用最后一个选项,那么您可能需要如下所示来添加以下内容:
services.AddDbContext<IdentityContext>(); //make sure it's same database as IdentityServer4
services.AddIdentityCore<ApplicationUser>(options => { });
new IdentityBuilder(typeof(ApplicationUser), typeof(IdentityRole), services)
.AddRoleManager<RoleManager<IdentityRole>>()
.AddSignInManager<SignInManager<ApplicationUser>>()
.AddEntityFrameworkStores<IdentityContext>();这将为您提供足够的服务来使用UserManager,并且不会设置任何不必要的身份验证方案。
由于关注点的分离,我不推荐最后一种方法--您的API应该关注提供资源,而不是创建用户和提供资源。第一和第二种方法在我看来是可以的,但我总是倾向于为AspNetIdentity管理提供干净的单独服务。
我们在其中一个项目中实现了这样的方法,这是一个示例体系结构:
发布于 2019-02-04 11:44:01
我和你有类似的情况。
我们的用例是,通常新用户将通过身份服务器创建。但是,我们也希望应用程序能够邀请用户。所以我可以登录申请,我想邀请我的朋友。这样的想法是,邀请的行为就像用户自己创建自己一样。
因此,它会发送一封电子邮件给我的朋友,并附上一个密码,然后用户将能够提供他们的密码,并有一个帐户。
为此,我在我的帐户控制器上创建了一个新的操作。
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> Invited([FromQuery] InviteUserRequest request)
{
if (request.Code == null)
{
RedirectToAction(nameof(Login));
}
var user = await _userManager.FindByIdAsync(request.UserId.ToString());
if (user == null)
{
return View("Error");
}
var validateCode = await _userManager.VerifyUserTokenAsync(user, _userManager.Options.Tokens.PasswordResetTokenProvider, "ResetPassword", Uri.UnescapeDataString(request.Code));
if (!validateCode)
{
return RedirectToAction(nameof(Login), new { message = ManageMessageId.PasswordResetFailedError, messageAttachment = "Invalid code." });
}
await _userManager.EnsureEmailConfirmedAsync(user);
await _userManager.EnsureLegacyNotSetAsync(user);
return View(new InvitedViewModel { Error = string.Empty, Email = user.Email, Code = request.Code, UserId = user.Id });
}当用户接受电子邮件时,我们会添加它们。
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Invited([FromForm] InvitedViewModel model)
{
if (!ModelState.IsValid)
{
model.Error = "invalid model";
return View(model);
}
if (!model.Password.Equals(model.ConfirmPassword))
{
model.Error = "Passwords must match";
return View(model);
}
if (model.Terms != null && !model.Terms.All(t => t.Accept))
{
return View(model);
}
var user = await _userManager.FindByEmailAsync(model.Email);
if (user == null)
{
// Don't reveal that the user does not exist
return RedirectToAction(nameof(Login), new { message = ManageMessageId.InvitedFailedError, messageAttachment = "User Not invited please invite user again." });
}
var result = await _userManager.ResetPasswordAsync(user, Uri.UnescapeDataString(model.Code), model.Password);
if (result.Succeeded)
{
return Redirect(_settings.Settings.XenaPath);
}
var errors = AddErrors(result);
return RedirectToAction(nameof(Login), new { message = ManageMessageId.InvitedFailedError, messageAttachment = errors });
}这样做的原因是,只有身份服务器应该读取和写入其数据库。api和第三方应用程序不应该需要直接更改由另一个应用程序控制的数据库。因此,以这种方式,API告诉标识服务器邀请用户,然后身份服务器控制其他一切。
此外,通过这样做,它消除了API中有用户管理器的需求:)
发布于 2020-08-20 10:54:24
我不建议您在不同API之间使用共享数据库,如果您需要使用附加API扩展Identity Server 4,您可以使用LocalApiAuthentication作为控制器。
https://stackoverflow.com/questions/54493921
复制相似问题