如果你只想登录Google,就不需要
SignInManager
,
UserManager
或ASP.NET核心标识本身。为了实现这一点,我们首先需要配置身份验证服务。下面是相关的代码,我将在下面解释:
创业公司
services
.AddAuthentication(o =>
{
o.DefaultScheme = "Application";
o.DefaultSignInScheme = "External";
})
.AddCookie("Application")
.AddCookie("External")
.AddGoogle(o =>
{
o.ClientId = ...;
o.ClientSecret = ...;
});
-
呼唤
AddAuthentication
配置一个
DefaultScheme
最后被用作
应用程序
方案与
挑战
方案。这个
应用
尝试验证用户身份时使用方案(他们是否登录?). The
挑战
当用户
不
已登录,但应用程序希望提供这样做的选项。我来讨论一下
DefaultSignInScheme
后来。
-
两个电话
AddCookie
为两者添加基于cookie的身份验证方案
Application
(我们的
应用
方案)
External
(我们的
信号素
方案)。
加法饼干
也可以采用第二个参数,允许配置相应的cookie的生存期等。
有了这一点,挑战过程将把用户重定向到
/Account/Login
(默认情况下-也可以通过cookie身份验证选项进行配置)。下面是一个控制器实现,它处理挑战过程(稍后我将再次解释):
会计总监.cs
public class AccountController : Controller
{
public IActionResult Login(string returnUrl)
{
return new ChallengeResult(
GoogleDefaults.AuthenticationScheme,
new AuthenticationProperties
{
RedirectUri = Url.Action(nameof(LoginCallback), new { returnUrl })
});
}
public async Task<IActionResult> LoginCallback(string returnUrl)
{
var authenticateResult = await HttpContext.AuthenticateAsync("External");
if (!authenticateResult.Succeeded)
return BadRequest(); // TODO: Handle this better.
var claimsIdentity = new ClaimsIdentity("Application");
claimsIdentity.AddClaim(authenticateResult.Principal.FindFirst(ClaimTypes.NameIdentifier));
claimsIdentity.AddClaim(authenticateResult.Principal.FindFirst(ClaimTypes.Email));
await HttpContext.SignInAsync(
"Application",
new ClaimsPrincipal(claimsIdentity));
return LocalRedirect(returnUrl);
}
}
让我们将其分为两个操作:
-
Login
为了到达
登录
操作,用户将
挑战的
. 当用户未使用
应用
方案,但正在尝试访问受
Authorize
属性(或类似)。根据您的要求,如果用户未登录,我们希望使用Google登录。为了实现这一目标,我们发布了
新的
挑战,这次
Google
方案。我们使用
ChallengeResult
配置了
谷歌
方案与A
RedirectUrl
它用于在Google登录过程完成后返回我们自己的应用程序代码。如代码所示,我们返回到:
-
LoginCallback
这就是
默认签名方案
从我们的呼叫到
添加身份验证
变得相关。作为谷歌登录过程完成的一部分,
默认签名方案
用于设置包含
ClaimsPrincipal
表示从Google返回的用户(这都是在幕后处理的)。中的第一行代码
逻辑回调
抓住这个
索赔委托人
实例,它被包装在
AuthenticateResult
首先要检查是否成功。如果到目前为止一切都成功了,我们最终会创造一个新的
索赔委托人
它包含我们需要的任何声明(在本例中是从Google获取的),然后登录
索赔委托人
使用
应用
方案。最后,我们重定向到导致我们的第一个
挑战
.
我创建了一个Github存储库,其中包含一个完整的示例,我构建它是为了写出这个答案。
here
.
针对以下评论中的几个后续评论/问题:
我能得出结论吗
信号管理器
和
中央层
仅在对数据库使用身份验证时使用?
在某些方面,是的,我认为这是公平的。虽然可以实现内存中的存储,但是如果没有持久性,它就没有多大意义。但是,在您的情况下不使用这些类的真正原因只是因为您不需要本地用户帐户来表示用户。这与坚持不懈是紧密相连的,但值得加以区分。
和我在书中读到的(我用来设置我的Google登录)以及我读过的所有其他答案有什么不同。
文档和书籍涵盖了最常见的用例,因此
做
希望存储可以
链接
到外部帐户,如google等
信号管理器
源代码,您会发现它实际上只是位于我上面显示的代码类型之上(例如
here
和
here
)其他代码可以在默认用户界面中找到(例如
here
以及在
AddIdentity
.
我假设Logincallback被Google调用。httpContext.authenticateAsync知道如何检查Google发送给我的数据吗?由于它的名字非常通用,看起来它知道如何为所有外部提供者做到这一点?
呼唤
AuthenticateAsync
这里不知道
任何东西
关于google-通过调用配置google特定的处理
AddGoogle
关闭
添加身份验证
在里面
ConfigureServices
.在重定向到Google进行登录后,我们实际上回到了
/signin-google
在我们的应用程序中。同样,这是由于
阿德哥格尔
,但该代码实际上只是在
外部
存储来自谷歌的声明,然后重定向到我们的
登陆车
我们配置的端点。如果您将呼叫添加到
AddFacebook
A
/sigin-facebook
端点将被配置为执行类似的操作。呼唤
身份验证同步
真的只是补液
索赔原则
从创建的cookie中,例如
谷歌
终结点,以便检索声明。
值得注意的是,Google/Facebook登录过程基于
OAuth 2 protocol
所以它本身就是一种通用的。如果你需要的不仅仅是Google的支持,你只需要针对所需的方案发布挑战,而不是像我在示例中所做的那样将其硬编码到Google。还可以向挑战添加其他属性,以便能够确定在
登陆车
已到达终结点。