asp.net-core - ASP.NET Core 使用没有 Razor 页面的 IdentityUser 绑定外部登录
问题描述
我正在尝试将 GitHub 身份验证添加到我的 ASP.NET Core 应用程序,以便某些用户具有管理员角色。我想要实现的这个角色IdentityRole
,用户应该存储为IdentityUser
s。
我使用这篇文章中的信息作为起点。
我通过 GitHub 设置身份验证,如下所示:
services
.AddAuthentication()
.AddGitHub(options =>
{
options.ClientId = "xxx";
options.ClientSecret = "xxx";
})
我在控制器中的 Sigin 方法在这里:
public IActionResult SignIn(string provider, string returnUrl = null) =>
Challenge(new AuthenticationProperties { RedirectUri = returnUrl ?? "/" }, provider);
我可以通过以下代码获得 GitHub 声明:
public IActionResult Index()
{
var vm = new ProfileViewModel
{
Claims = User.Claims,
Name = User.Identity.Name
};
return View(vm);
}
一切正常,一切都很好,但事实ClaimsPrincipal
并非如此IdentityUser
。而且我不明白如何IdentityUser
使用此声明创建新的或标识以前存储的。以下是微软关于使用外部登录的一组文章,但他们使用了 Razor 页面并且没有提供太多信息它实际上是如何绑定到IdentityUser
.
在不使用 Razor 页面的情况下如何做同样的事情?
解决方案
要将 github 用户映射到身份用户,您需要创建身份用户。
要创建没有 Razor 页面的 IdentityUser,您需要构建请求以将所需信息发送到ExternalLoginConfirmation
.
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
if (remoteError != null)
{
ErrorMessage = $"Error from external provider: {remoteError}";
return RedirectToAction(nameof(Login));
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToAction(nameof(Login));
}
// Sign in the user with this external login provider if the user already has a login.
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
if (result.Succeeded)
{
_logger.LogInformation("User logged in with {Name} provider.", info.LoginProvider);
return RedirectToLocal(returnUrl);
}
if (result.IsLockedOut)
{
return RedirectToAction(nameof(Lockout));
}
else
{
// If the user does not have an account, then ask the user to create an account.
ViewData["ReturnUrl"] = returnUrl;
ViewData["LoginProvider"] = info.LoginProvider;
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
return View("ExternalLogin", new ExternalLoginViewModel { Email = email });
}
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginViewModel model, string returnUrl = null)
{
if (ModelState.IsValid)
{
// Get the information about the user from the external login provider
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
throw new ApplicationException("Error loading external login information during confirmation.");
}
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user);
if (result.Succeeded)
{
result = await _userManager.AddLoginAsync(user, info);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
_logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider);
return RedirectToLocal(returnUrl);
}
}
AddErrors(result);
}
ViewData["ReturnUrl"] = returnUrl;
return View(nameof(ExternalLogin), model);
}
推荐阅读
- angular - Service Workers Angular 在 URL 中使用版本参数加载资产
- chisel - 将 OpenSoCFabric1.1.2 从 Chisel2 重写为 Chisel3 时,“要连接的数据 'chisel3.core.UInt@103' 必须是硬件,而不是裸凿类型”
- delphi - 在 Windows 平台上使用 Delphi TZipfile 创建的 Zip 文件不能移植到其他操作系统
- html - 引号内的html文本
- wordpress - WordPress - 从 *.csv 文件导入电子邮件订阅
- azure - 使用 azure datafactory SSIS 将 zip 文件上传到 blob 存储的脚本任务
- python - Python:使用管道作为分隔符分隔字符串
- arrays - Python:相应地循环每一列/行并减去两个csv文件之间的值
- angular - 角度无法设置值以形成控制
- node.js - 如何用 Jest 模拟所需的模块功能?