AspNetCore3.1_Secutiry源碼解析_7_Authentication_其他

来源:https://www.cnblogs.com/holdengong/archive/2020/03/26/12573967.html
-Advertisement-
Play Games

title: "AspNetCore3" date: 2020 03 26T13:23:27+08:00 draft: false 系列文章目錄 "AspNetCore3.1_Secutiry源碼解析_1_目錄" "AspNetCore3.1_Secutiry源碼解析_2_Authenticatio ...



title: "AspNetCore3"
date: 2020-03-26T13:23:27+08:00
draft: false

系列文章目錄

簡介

Secutiry的認證目錄還有這些項目,基本都是具體的OAuth2.0服務商或者其他用的比較少的認證架構,簡單看一下,瞭解一下。

  • Microsoft.AspNetCore.Authentication.Certificate
  • Microsoft.AspNetCore.Authentication.Facebook
  • Microsoft.AspNetCore.Authentication.Google
  • Microsoft.AspNetCore.Authentication.MicrosoftAccount
  • Microsoft.AspNetCore.Authentication.Negotiate
  • Microsoft.AspNetCore.Authentication.Twitter
  • Microsoft.AspNetCore.Authentication.WsFederation

OAuth2.0服務商

Facebook, Google,MicrosoftAccount這幾個都可以歸為一類,都是OAuth2.0的服務商。國內用的比較多的是QQ,Weixin。我們看一下Facebook的代碼,其他的原理都是大同小異的,根據不同廠商的差異稍作調整就可以了。

Twitter似乎是用的OAuth1.0協議。

依賴註入

配置類: FacebookOptions,處理器類:FacebookHandler

public static class FacebookAuthenticationOptionsExtensions
{
    public static AuthenticationBuilder AddFacebook(this AuthenticationBuilder builder)
        => builder.AddFacebook(FacebookDefaults.AuthenticationScheme, _ => { });

    public static AuthenticationBuilder AddFacebook(this AuthenticationBuilder builder, Action<FacebookOptions> configureOptions)
        => builder.AddFacebook(FacebookDefaults.AuthenticationScheme, configureOptions);

    public static AuthenticationBuilder AddFacebook(this AuthenticationBuilder builder, string authenticationScheme, Action<FacebookOptions> configureOptions)
        => builder.AddFacebook(authenticationScheme, FacebookDefaults.DisplayName, configureOptions);

    public static AuthenticationBuilder AddFacebook(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<FacebookOptions> configureOptions)
        => builder.AddOAuth<FacebookOptions, FacebookHandler>(authenticationScheme, displayName, configureOptions);
}

配置類 - FacebookOptions

配置類繼承自OAuthOptions,構造函數根據Facebook做了一些定製處理,如claim的映射等。

/// <summary>
/// Configuration options for <see cref="FacebookHandler"/>.
/// </summary>
public class FacebookOptions : OAuthOptions
{
    /// <summary>
    /// Initializes a new <see cref="FacebookOptions"/>.
    /// </summary>
    public FacebookOptions()
    {
        CallbackPath = new PathString("/signin-facebook");
        SendAppSecretProof = true;
        AuthorizationEndpoint = FacebookDefaults.AuthorizationEndpoint;
        TokenEndpoint = FacebookDefaults.TokenEndpoint;
        UserInformationEndpoint = FacebookDefaults.UserInformationEndpoint;
        Scope.Add("email");
        Fields.Add("name");
        Fields.Add("email");
        Fields.Add("first_name");
        Fields.Add("last_name");

        ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
        ClaimActions.MapJsonSubKey("urn:facebook:age_range_min", "age_range", "min");
        ClaimActions.MapJsonSubKey("urn:facebook:age_range_max", "age_range", "max");
        ClaimActions.MapJsonKey(ClaimTypes.DateOfBirth, "birthday");
        ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
        ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
        ClaimActions.MapJsonKey(ClaimTypes.GivenName, "first_name");
        ClaimActions.MapJsonKey("urn:facebook:middle_name", "middle_name");
        ClaimActions.MapJsonKey(ClaimTypes.Surname, "last_name");
        ClaimActions.MapJsonKey(ClaimTypes.Gender, "gender");
        ClaimActions.MapJsonKey("urn:facebook:link", "link");
        ClaimActions.MapJsonSubKey("urn:facebook:location", "location", "name");
        ClaimActions.MapJsonKey(ClaimTypes.Locality, "locale");
        ClaimActions.MapJsonKey("urn:facebook:timezone", "timezone");
    }

    /// <summary>
    /// Check that the options are valid.  Should throw an exception if things are not ok.
    /// </summary>
    public override void Validate()
    {
        if (string.IsNullOrEmpty(AppId))
        {
            throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, nameof(AppId)), nameof(AppId));
        }

        if (string.IsNullOrEmpty(AppSecret))
        {
            throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, nameof(AppSecret)), nameof(AppSecret));
        }

        base.Validate();
    }

    // Facebook uses a non-standard term for this field.
    /// <summary>
    /// Gets or sets the Facebook-assigned appId.
    /// </summary>
    public string AppId
    {
        get { return ClientId; }
        set { ClientId = value; }
    }

    // Facebook uses a non-standard term for this field.
    /// <summary>
    /// Gets or sets the Facebook-assigned app secret.
    /// </summary>
    public string AppSecret
    {
        get { return ClientSecret; }
        set { ClientSecret = value; }
    }

    /// <summary>
    /// Gets or sets if the appsecret_proof should be generated and sent with Facebook API calls.
    /// This is enabled by default.
    /// </summary>
    public bool SendAppSecretProof { get; set; }

    /// <summary>
    /// The list of fields to retrieve from the UserInformationEndpoint.
    /// https://developers.facebook.com/docs/graph-api/reference/user
    /// </summary>
    public ICollection<string> Fields { get; } = new HashSet<string>();
}

處理器類

重寫了OAuthHanlder的創建憑據方法,其他的都是使用的父類實現。

public class FacebookHandler : OAuthHandler<FacebookOptions>
{
    public FacebookHandler(IOptionsMonitor<FacebookOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
        : base(options, logger, encoder, clock)
    { }

    protected override async Task<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens)
    {
        var endpoint = QueryHelpers.AddQueryString(Options.UserInformationEndpoint, "access_token", tokens.AccessToken);
        if (Options.SendAppSecretProof)
        {
            endpoint = QueryHelpers.AddQueryString(endpoint, "appsecret_proof", GenerateAppSecretProof(tokens.AccessToken));
        }
        if (Options.Fields.Count > 0)
        {
            endpoint = QueryHelpers.AddQueryString(endpoint, "fields", string.Join(",", Options.Fields));
        }

        var response = await Backchannel.GetAsync(endpoint, Context.RequestAborted);
        if (!response.IsSuccessStatusCode)
        {
            throw new HttpRequestException($"An error occurred when retrieving Facebook user information ({response.StatusCode}). Please check if the authentication information is correct and the corresponding Facebook Graph API is enabled.");
        }

        using (var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync()))
        {
            var context = new OAuthCreatingTicketContext(new ClaimsPrincipal(identity), properties, Context, Scheme, Options, Backchannel, tokens, payload.RootElement);
            context.RunClaimActions();
            await Events.CreatingTicket(context);
            return new AuthenticationTicket(context.Principal, context.Properties, Scheme.Name);
        }
    }

    private string GenerateAppSecretProof(string accessToken)
    {
        using (var algorithm = new HMACSHA256(Encoding.ASCII.GetBytes(Options.AppSecret)))
        {
            var hash = algorithm.ComputeHash(Encoding.ASCII.GetBytes(accessToken));
            var builder = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                builder.Append(hash[i].ToString("x2", CultureInfo.InvariantCulture));
            }
            return builder.ToString();
        }
    }

    protected override string FormatScope(IEnumerable<string> scopes)
    {
        // Facebook deviates from the OAuth spec here. They require comma separated instead of space separated.
        // https://developers.facebook.com/docs/reference/dialogs/oauth
        // http://tools.ietf.org/html/rfc6749#section-3.3
        return string.Join(",", scopes);
    }

    protected override string FormatScope()
        => base.FormatScope();
}

Microsoft.AspNetCore.Authentication.Certificate

這個項目是3.1新加的,是做證書校驗的,具體的不細說了,不太懂,有興趣的看巨硬文檔

https://docs.microsoft.com/zh-cn/aspnet/core/security/authentication/certauth?view=aspnetcore-3.1

Microsoft.AspNetCore.Authentication.Negotiate

這個也是新增的項目,是做Windows校驗的,文檔如下

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.1&tabs=visual-studio

Microsoft.AspNetCore.Authentication.WsFederation

Windows的Azure Active Directory認證

https://docs.microsoft.com/zh-cn/aspnet/core/security/authentication/ws-federation?view=aspnetcore-3.1


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • QRCoder是一個簡單的庫,用C#.NET編寫,可讓您創建QR碼。 它與其他庫沒有任何依賴關係,並且可以在NuGet上以.NET Framework和.NET Core PCL版本獲得。 有關更多信息,請參見:QRCode Wiki | 創作者的博客(英語)| 創作者的博客(德語) QRCo... ...
  • 一直以來都是更新為一些簡單的基礎類型,直到有一天寫了一個覆蓋某一個欄位(這個欄位為數組)的更新操作。出問題了,資料庫中出現了_t,_v……有點懵了。當然如果我們更新的時候設置類型是不會出現這個問題的,出現這種問題的一個前提是我們將數組賦值給了object類型的變數;由於時間關係問了一下同事,她給出了 ...
  • 1.生成的Dockerfile 拿到外層根目錄(ps:生成Dockerfile文件需要選擇linux) 2.控制台進入對應文件夾 3.docker build -t debugbox/api(debugbox/api是給項目起的名)a . (這裡的點代表當前目錄)(loading…… 生成鏡像) 4 ...
  • 分散式部署服務的情況下,由於網路狀況不可預期,消息有可能發送成功,但是消費端消費失敗;也有可能消息根本沒有發出去,如何保證消息是否發送成功是經常遇到的問題。最近有時間研究了一下,具體方法如下圖: 表結構設計如下: 具體思路: 正常流程(網路都正常) 1.消息生產方,將消息信息與業務數據在同一個事務中 ...
  • 目錄 "identityserver4源碼解析_1_項目結構" "identityserver4源碼解析_2_元數據介面" "identityserver4源碼解析_3_認證介面" "identityserver4源碼解析_4_令牌發放介面" "identityserver4源碼解析_5_查詢用戶信 ...
  • 目錄 "identityserver4源碼解析_1_項目結構" "identityserver4源碼解析_2_元數據介面" "identityserver4源碼解析_3_認證介面" "identityserver4源碼解析_4_令牌發放介面" "identityserver4源碼解析_5_查詢用戶信 ...
  • 目錄 "identityserver4源碼解析_1_項目結構" "identityserver4源碼解析_2_元數據介面" "identityserver4源碼解析_3_認證介面" "identityserver4源碼解析_4_令牌發放介面" "identityserver4源碼解析_5_查詢用戶信 ...
  • 目錄 "AspNetCore3.1_Secutiry源碼解析_1_目錄" "AspNetCore3.1_Secutiry源碼解析_2_Authentication_核心流程" "AspNetCore3.1_Secutiry源碼解析_3_Authentication_Cookies" "AspNetC ...
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...