zoukankan      html  css  js  c++  java
  • 第22章 使用外部身份提供商登录

    ASP.NET Core有一种灵活的方式来处理外部身份验证。这涉及几个步骤。

    注意
    如果您使用的是ASP.NET Identity,则会隐藏许多基础技术细节。建议您还阅读Microsoft 文档并执行ASP.NET Identity 快速入门

    22.1 为外部提供者添加身份验证处理程序

    与外部提供者通信所需的协议实现封装在身份验证处理程序中。一些提供商使用专有协议(例如Facebook等社交提供商),有些提供商使用标准协议,例如OpenID Connect,WS-Federation或SAML2p。

    有关添加外部身份验证和配置它的分步说明,请参阅此快速入门

    22.2 cookies的作用

    调用外部身份验证处理程序的一个选项SignInScheme,例如:

    services.AddAuthentication()
        .AddGoogle("Google", options =>
        {
            options.SignInScheme = "scheme of cookie handler to use";
    
            options.ClientId = "...";
            options.ClientSecret = "...";
        })
    

    登录方案指定将临时存储外部认证结果的cookie处理程序的名称,例如由外部提供者发送的声明。这是必要的,因为在完成外部身份验证过程之前通常会涉及一些重定向。

    鉴于这是一种常见做法,IdentityServer专门为此外部提供程序工作流注册cookie处理程序。该方案通过IdentityServerConstants.ExternalCookieAuthenticationScheme常数表示。如果您要使用我们的外部cookie处理程序,那么对于SignInScheme上面的内容,您将赋值为IdentityServerConstants.ExternalCookieAuthenticationScheme常量:

    services.AddAuthentication()
        .AddGoogle("Google", options =>
        {
            options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
    
            options.ClientId = "...";
            options.ClientSecret = "...";
        })
    

    您也可以注册自己的自定义cookie处理程序,如下所示:

    services.AddAuthentication()
        .AddCookie("YourCustomScheme")
        .AddGoogle("Google", options =>
        {
            options.SignInScheme = "YourCustomScheme";
    
            options.ClientId = "...";
            options.ClientSecret = "...";
        })
    

    注意
    对于特殊情况,您还可以将外部cookie机制短路并将外部用户直接转发到主cookie处理程序。这通常涉及处理外部处理程序上的事件,以确保您从外部标识源执行正确的声明转换。

    22.3 触发认证处理程序

    您可以通过(或使用MVCChallengeResultHttpContext上的ChallengeAsync扩展方法调用外部认证处理程序。

    您通常希望将一些选项传递给挑战操作,例如回调页面的路径和簿记提供者的名称,例如:

    var callbackUrl = Url.Action("ExternalLoginCallback");
    
    var props = new AuthenticationProperties
    {
        RedirectUri = callbackUrl,
        Items =
        {
            { "scheme", provider },
            { "returnUrl", returnUrl }
        }
    };
    
    return Challenge(provider, props);
    

    22.4 处理回调并签署用户

    在回调页面上,您的典型任务是:

    • 检查外部提供商返回的身份。
    • 决定如何处理该用户。如果这是新用户或返回用户,则可能会有所不同。
    • 新用户在被允许之前可能需要额外的步骤和UI。
    • 可能会创建一个链接到外部提供程序的新内部用户帐户。
    • 存储您要保留的外部声明。
    • 删除临时cookie
    • 登录用户

    22.4.1 检查外部身份:

    // read external identity from the temporary cookie
    var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
    if (result?.Succeeded != true)
    {
        throw new Exception("External authentication error");
    }
    
    // retrieve claims of the external user
    var externalUser = result.Principal;
    if (externalUser == null)
    {
        throw new Exception("External authentication error");
    }
    
    // retrieve claims of the external user
    var claims = externalUser.Claims.ToList();
    
    // try to determine the unique id of the external user - the most common claim type for that are the sub claim and the NameIdentifier
    // depending on the external provider, some other claim type might be used
    var userIdClaim = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject);
    if (userIdClaim == null)
    {
        userIdClaim = claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier);
    }
    if (userIdClaim == null)
    {
        throw new Exception("Unknown userid");
    }
    
    var externalUserId = userIdClaim.Value;
    var externalProvider = userIdClaim.Issuer;
    
    // use externalProvider and externalUserId to find your user, or provision a new user
    

    22.4.2 清理和登录:

    // issue authentication cookie for user
    await HttpContext.SignInAsync(user.SubjectId, user.Username, provider, props, additionalClaims.ToArray());
    
    // delete temporary cookie used during external authentication
    await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
    
    // validate return URL and redirect back to authorization endpoint or a local page
    if (_interaction.IsValidReturnUrl(returnUrl) || Url.IsLocalUrl(returnUrl))
    {
        return Redirect(returnUrl);
    }
    
    return Redirect("~/");
    

    22.5 状态,URL长度和ISecureDataFormat

    重定向到外部提供程序进行登录时,必须经常从客户端应用程序进行往返状态。这意味着在离开客户端之前捕获状态并保留状态,直到用户返回到客户端应用程序。许多协议(包括OpenID Connect)允许将某种状态作为参数传递作为请求的一部分,并且身份提供者将在响应上返回该状态。ASP.NET Core提供的OpenID Connect身份验证处理程序利用协议的这一功能,即它实现上述returnUrl功能的方式。

    在请求参数中存储状态的问题是请求URL可能变得太大(超过2000个字符的公共限制)。OpenID Connect身份验证处理程序确实提供了一个可扩展点,用于在服务器中而不是在请求URL中存储状态。您可以通过ISecureDataFormat<AuthenticationProperties>OpenIdConnectOptions上实现和配置它来自行实现。

    幸运的是,IdentityServer为您提供了一个实现,由IDistributedCache DI容器中注册的实现(例如标准MemoryDistributedCache)支持。要使用IdentityServer提供的安全数据格式实现,只需在配置DI时调用IServiceCollection扩展AddOidcStateDataFormatterCache方法。如果未传递任何参数,则配置的所有OpenID Connect处理程序将使用IdentityServer提供的安全数据格式实现:

    public void ConfigureServices(IServiceCollection services)
    {
        // configures the OpenIdConnect handlers to persist the state parameter into the server-side IDistributedCache.
        services.AddOidcStateDataFormatterCache();
    
        services.AddAuthentication()
            .AddOpenIdConnect("demoidsrv", "IdentityServer", options =>
            {
                // ...
            })
            .AddOpenIdConnect("aad", "Azure AD", options =>
            {
                // ...
            })
            .AddOpenIdConnect("adfs", "ADFS", options =>
            {
                // ...
            });
    }
    

    如果只配置特定方案,则将这些方案作为参数传递:

    public void ConfigureServices(IServiceCollection services)
    {
        // configures the OpenIdConnect handlers to persist the state parameter into the server-side IDistributedCache.
        services.AddOidcStateDataFormatterCache("aad", "demoidsrv");
    
        services.AddAuthentication()
            .AddOpenIdConnect("demoidsrv", "IdentityServer", options =>
            {
                // ...
            })
            .AddOpenIdConnect("aad", "Azure AD", options =>
            {
                // ...
            })
            .AddOpenIdConnect("adfs", "ADFS", options =>
            {
                // ...
            });
    }
    

    github地址

  • 相关阅读:
    android systembar tabletUI
    linux mv
    修改framework/base下面的api要注意要修改的地方
    git 从远程主服务器当中创建新分支
    修改android framework 添加service
    DUILIB 界面基本知识
    Duilib vlc c++ 字符编码
    android 应用APK使用系统APK
    linux 查找文件内容及文件
    修改android 开机动画
  • 原文地址:https://www.cnblogs.com/thinksjay/p/10774864.html
Copyright © 2011-2022 走看看