在ASP中连接OAuth与用户或人员模型.Net MVC c#
本文关键字:模型 Net MVC 用户 ASP 连接 OAuth | 更新日期: 2023-09-27 18:06:09
所以网上有很多关于如何让oAuth使用ASP的教程。. NET,甚至还有一个关于如何为那些使用MVC登录的帐户设置角色的教程,但这些教程都没有解释接下来的内容。当你将一个在谷歌注册的用户连接到你应用中的人或用户模型时它叫什么?根据你在谷歌上登录的身份,你如何作为其中的一员行事?我已经知道如何注册名字和姓氏之类的东西了,但我仍然不确定如何让我在里面或扮演那个人。
例如,我有一个人员模型和一些继承自该人员模型的其他模型,例如Engineer和Manager:
public class Person
{
[Key]
public int PersonId { get; set; }
[Required(ErrorMessage = "The First Name field is required.")]
[Display(Name = "First Name")]
[MaxLength(50)]
public string FirstName { get; set; }
[Required(ErrorMessage = "The Last Name field is required.")]
[Display(Name = "Last Name")]
[MaxLength(50)]
public string LastName { get; set; }
[NotMapped]
[Display(Name = "Name")]
public string FullName
{
get
{
return FirstName + " " + LastName;
}
}
}
public class Engineer : Person
{
public ICollection<Manager> managers { get; set; }
}
public class Manager : Person
{
public ICollection<Engineer> engineers { get; set; }
}
这里我在AccountController中添加了以下内容:
[AllowAnonymous]
public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
{
string firstName;
string lastName;
var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
return RedirectToAction("Login");
}
if (loginInfo.Login.LoginProvider == "Google")
{
var externalIdentity = AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);
var emailClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email);
var lastNameClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Surname);
var givenNameClaim = externalIdentity.Result.Claims.FirstOrDefault(c => c.Type == ClaimTypes.GivenName);
firstName = givenNameClaim.Value;
lastName = lastNameClaim.Value;
} else
{
firstName = "Error";
lastName = "Error";
}
// Sign in the user with this external login provider if the user already has a login
var result = await SignInManager.ExternalSignInAsync(loginInfo, isPersistent: false);
switch (result)
{
case SignInStatus.Success:
return RedirectToLocal(returnUrl);
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = false });
case SignInStatus.Failure:
default:
// If the user does not have an account, then prompt the user to create an account
ViewBag.ReturnUrl = returnUrl;
ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email, FirstName = firstName, LastName = lastName });
}
和帐户视图模型:
public class ExternalLoginConfirmationViewModel
{
[Required]
[Display(Name = "Email")]
public string Email { get; set; }
[Required]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Required]
[Display(Name = "Last Name")]
public string LastName { get; set; }
}
那么我如何登录谷歌并成为其中一员呢?这叫什么来着?这样做有什么名字吗?我想每个人都有过这样的经历。我可以在我的初始化类中创建人员,经理和工程师,但我不知道如何使用oAuth。
注意,我更愿意强制所有用户登录谷歌而不是创建一个本地用户帐户,所以我没有麻烦注册网站帐户。
这里是我的IdentityModel:
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
在外部登录过程中,第三方API返回一个授权令牌。您应该添加这个令牌作为用户的声明。您可以通过将Startup.Auth.cs
中的代码更改为以下内容来实现此目的:
var googleOptions = new GoogleOAuth2AuthenticationOptions
{
ClientId = Properties.Settings.Default.GoogleClientId,
ClientSecret = Properties.Settings.Default.GoogleClientSecret,
Provider = new GoogleOAuth2AuthenticationProvider
{
OnAuthenticated = (context) =>
{
context.Identity.AddClaim(new System.Security.Claims.Claim("urn:google:access_token", context.AccessToken, XmlSchemaString, "Google"));
return Task.FromResult(0);
}
}
};
googleOptions.Scope.Add("foo");
app.UseGoogleAuthentication(googleOptions);
如果"foo"在上面,您需要添加需要用户授权应用程序的范围。有关作用域的完整列表,请参阅Google API文档。如果需要多个作用域,请添加额外的googleOptions.Scope.Add
行。
var googleTokenClaim = user.Claims.FirstOrDefault(m => m.ClaimType.EndsWith("google:access_token"));
对于Google的api,返回的令牌是一个"刷新令牌"。刷新令牌在用户撤销对应用程序的访问权限之前是有效的,但你需要将其"交换"为访问令牌。关于如何做到这一点的详细信息可以在Google Identity Platform文档中找到,或者您可以使用其中一个客户端库来为您处理所有这些。
长和短,一旦你有一个真正的访问令牌,你只需授权需要授权的请求通过添加一个Authorization: Bearer [token]
头到请求。
现在,不同的api处理其中的一些不同,但你特别提到了谷歌。参考您可能需要使用的其他api的文档,以了解您应该如何使用它们。
UPDATE: Getting User Instance
对于Identity, User.Identity
公开的用户主体并不是数据库中用户实例的完整表示。为了获得用户的所有信息,包括他们的声明,您需要从数据库中查询用户。首先,您需要获得用户的id,这样您就有了查询的依据。标识在User.Identity
上公开扩展GetUserId()
:
var userId = User.Identity.GetUserId();
如果您已经为IdentityUser
定制了主键,那么您需要使用通用版本:
var userId = User.Identity.GetUserId<int>();
无论哪种情况,您都可以使用该用户id从数据库中查询该用户。实际上,您可以直接查询上下文,因为"users"只是IdentityDbContext
上的另一个DbSet
:
var user = db.Users.Find(userId);
然而,您将经常使用UserManager
的实例,因为它本质上包装了您的上下文并提供了额外的、有用的特性:
var user = UserManager.FindById(userId);
这是基于AccountController
的默认实现,当您使用个人身份验证搭建项目时。默认情况下,AccountController
上的UserManager
属性是UserManager<ApplicationUser>
的一个实例,或者如果您自定义了主键,例如UserManager<ApplicationUser, int>
,其中int
将是主键的类型。如果您在不同的控制器中执行此操作,或者只是不使用AccountController
的支架版本,那么您只需要类似地定义UserManager
的实例。