[ASP.NET MVC] ASP.NET Identity登入技術應用

来源:http://www.cnblogs.com/clark159/archive/2016/02/17/5195673.html
-Advertisement-
Play Games

[ASP.NET MVC] ASP.NET Identity登入技術應用 情景 ASP.NET Identity是微軟所貢獻的開源項目,用來提供ASP.NET的驗證、授權等等機制。在ASP.NET Identity里除了提供最基礎的:用戶註冊、密碼重設、密碼驗證等等基礎功能之外,也提供了進階的:Co


[ASP.NET MVC] ASP.NET Identity登入技術應用

情景

ASP.NET Identity是微軟所貢獻的開源項目,用來提供ASP.NET的驗證、授權等等機制。在ASP.NET Identity里除了提供最基礎的:用戶註冊、密碼重設、密碼驗證等等基礎功能之外,也提供了進階的:Cookie登入、Facebook登入、Google登入等等進階功能。套用這些功能模塊,讓開發人員可以快速的在ASP.NET站臺上,提供驗證、授權等等機制。

情景01

但是在企業中,開發人員常常會遇到一種開發情景就是:企業里已經有一套既有身分系統,這個系統提供了:用戶註冊、密碼重設、密碼驗證等等功能,新開發的ASP.NET站臺,必須要串接既有身分系統來提供驗證、授權等等機制。這個既有身分系統,可能是大賣場會員管理系統、也可能是銀行帳戶管理系統,它們的註冊審核機制有一套嚴謹並且固定的流程。

在這樣的開發情景中,開發人員可能會選擇透過程式介面、OAuth機制等等方式,將既有身分系統整合成為ASP.NET Identity的驗證提供者。這樣兩個系統之間的整合,除了有一定的高技術門坎之外。在整合之後,兩個系統之間互相重迭的功能模塊,操作流程的衝突該如何處理,也是一個需要額外考慮的複雜問題。

情景02

一個好消息是,ASP.NET Identity擁有高度模塊化的軟體架構。在ASP.NET Identity中,將Cookie登入、Facebook登入、Google登入等等功能模塊,切割為獨立的ASP.NET Security套件。開發人員完全可以直接套用ASP.NET Security套件,快速整合既有的身分系統,就可以提供ASP.NET站臺所需的驗證、授權等等機制。本篇文章介紹如何套用ASP.NET Security來整合既有身分系統,用以提供ASP.NET站臺所需的驗證、授權等等機制。主要為自己留個紀錄,也希望能幫助到有需要的開發人員。

ASP.NET Security - GitHub

情景03

範例

範常式序代碼:下載地址

開發

開始套用ASP.NET Security之前,先建立一個空白的MVC項目,來提供一個新的ASP.NET站臺。並且變更預設的Web伺服器URL為:「http://localhost:41532/」,方便完成後續的開發步驟。

開發01

開發02

再來在MVC項目裡加入三個ASP.NET Security的NuGet套件參考:Microsoft.AspNet.Authentication、Microsoft.AspNet.Authentication.Cookies、Microsoft.AspNet.Authentication.Facebook。

開發03

接著建立AccountController以及相關的View,用以提供登入頁面,讓使用者可以選擇使用哪種模式登入系統。

public class AccountController : Controller
{
    // Methods
    public IActionResult Login(string returnUrl = null)
    {
        // ViewData
        this.ViewData["ReturnUrl"] = returnUrl;

        // Return
        return View();
    }
}

再來在MVC項目內加入下列程式代碼,用以掛載與設定後續要使用的兩個CookieAuthenticationMiddleware。(關於程式代碼的相關背景知識,請參閱技術剖析說明:ASP.NET Identity登入技術剖析)

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Authentication
        services.AddAuthentication(options =>
        {
            options.SignInScheme = IdentityOptions.Current.ExternalCookieAuthenticationScheme;
        });
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        // Authentication
        app.UseCookieAuthentication(options =>
        {
            options.AuthenticationScheme = IdentityOptions.Current.ApplicationCookieAuthenticationScheme;
            options.AutomaticAuthenticate = true;
            options.AutomaticChallenge = true;
            options.LoginPath = new PathString("/Account/login");
        });

        app.UseCookieAuthentication(options =>
        {
            options.AuthenticationScheme = IdentityOptions.Current.ExternalCookieAuthenticationScheme;
            options.AutomaticAuthenticate = false;
            options.AutomaticChallenge = false;
            options.LoginPath = null;
        });
    }
}

最後在MVC項目內,建立ExistingIdentitySystem這個類別用來模擬既有身分系統。為了方便理解系統,ExistingIdentitySystem里的PasswordSignIn(密碼登入)、ExternalSignIn(第三方登入ex:FB登入)等方法都直接回傳成功訊息,而GetUserById(取得使用者)這個方法則是直接回傳固定的用戶信息。(在正式環境開發時,上述方法可以實作為透過WebAPI、或是直接連通資料庫等等方式,與既有身分系統取得相關信息。)

public class ExistingIdentitySystem
{
    // Methods
    public ExistingUser GetUserById(string userId)
    {
        // Result
        var user = new ExistingUser();
        user.Id = "[email protected]";
        user.Name = "Clark";
        user.Birthday = DateTime.Now;

        // Return
        return user;
    }

    public bool PasswordSignIn(string userId, string password)
    {
        // Return
        return true;
    }

    public bool ExternalSignIn(string userId, string externalProvider)
    {
        switch (externalProvider)
        {
            case "Facebook": return true;

            default:
                return true;
        }
    }
}

public class ExistingUser
{
    // Properties
    public string Id { get; set; }

    public string Name { get; set; }

    public DateTime Birthday { get; set; }
}

開發 - Facebook Authentication

完成上述步驟後,接著著手開發Facebook驗證。首先開發人員可以到Facebook開發者中心(https://developers.facebook.com/),註冊一個新的APP賬號。(測試用的Site URL為先前步驟定義的:「http://localhost:41532/」)

開發Facebook01

接著在MVC項目內加入下列程式代碼,用以掛載與設定FacebookAuthenticationMiddleware。在這其中AppId、AppSecret是Facebook開發者中心提供的APP賬號數據,而Scope、UserInformationEndpoint兩個參數則是定義要額外取得用戶的E-Mail信息。

public class Startup
{
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        // Authentication
        app.UseFacebookAuthentication(options =>
        {                
            options.AppId = "770764239696406";
            options.AppSecret = "2eecc0b9ef785e43bcd4779e2803ba0f";
            options.Scope.Add("email");
            options.UserInformationEndpoint = "https://graph.facebook.com/v2.5/me?fields=id,name,email";
        });
    }
}

再來打開AccountController加入下列程式代碼以及對應的View,用以提供ASP.NET站臺處理Facebook這類的第三方登入(ExternalLogin)。在這其中,ExternalLogin用來發起一個驗證挑戰(Challenge),系統會依照externalProvider參數,來決定是要向Facebook或是其他第三方系統做驗證。

當用戶通過驗證後,系統會調用ExternalLoginCallback來處理驗證結果。在ExternalLoginCallback里會取得驗證結果中FBUser的UserId,用來與ExistingIdentitySystem做驗證。如果驗證通過,會接著從ExistingIdentitySystem取得對應的ExistingUser、再轉換為APPUser來真正登入系統。(關於程式代碼的相關背景知識,請參閱技術剖析說明:ASP.NET Identity登入技術剖析)

public class AccountController : Controller
{        
    public IActionResult ExternalLogin(string externalProvider, string returnUrl = null)
    {
        // AuthenticationProperties
        var authenticationProperties = new AuthenticationProperties();
        authenticationProperties.Items.Add("ExternalProvider", externalProvider);
        authenticationProperties.RedirectUri = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl });

        // Return
        return new ChallengeResult(externalProvider, authenticationProperties);
    }

    public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null)
    {
        // AuthenticateContext
        var authenticateContext = new AuthenticateContext(IdentityOptions.Current.ExternalCookieAuthenticationScheme);
        await this.HttpContext.Authentication.AuthenticateAsync(authenticateContext);

        // AuthenticateInfo           
        string userId = authenticateContext.Principal.FindFirst(ClaimTypes.Email).Value;
        string externalProvider = authenticateContext.Properties["ExternalProvider"] as string;

        // Login 
        var existingIdentitySystem = new ExistingIdentitySystem();
        if (existingIdentitySystem.ExternalSignIn(userId, externalProvider) == false)
        {
            throw new InvalidOperationException();
        }

        // ExistingUser
        var existingUser = existingIdentitySystem.GetUserById(userId);
        if (existingUser == null) throw new InvalidOperationException();

        // ApplicationUser
        var applicationIdentity = new ClaimsIdentity(IdentityOptions.Current.ApplicationCookieAuthenticationScheme, ClaimTypes.Name, ClaimTypes.Role);
        applicationIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, existingUser.Id));
        applicationIdentity.AddClaim(new Claim(ClaimTypes.Name, existingUser.Name));

        var applicationUser = new ClaimsPrincipal(applicationIdentity);

        // Cookie
        await this.HttpContext.Authentication.SignInAsync(IdentityOptions.Current.ApplicationCookieAuthenticationScheme, applicationUser);
        await this.HttpContext.Authentication.SignOutAsync(IdentityOptions.Current.ExternalCookieAuthenticationScheme);

        // Return
        return Redirect(returnUrl);
    }
}

開發 - Password Authentication

完成上述步驟後,接著著手開發Password驗證。打開AccountController加入下列程式代碼以及對應的View,用以提供ASP.NET站臺處理Password驗證。在這其中,PasswordLogin會接收用戶輸入的賬號密碼,用來與ExistingIdentitySystem做驗證。如果驗證通過,會接著從ExistingIdentitySystem取得ExistingUser、再轉換為APPUser來真正登入系統。(關於程式代碼的相關背景知識,請參閱技術剖析說明:ASP.NET Identity登入技術剖析)

public class AccountController : Controller
{
    public async Task<IActionResult> PasswordLogin(string userId, string password, string returnUrl = null)
    {
        // Login 
        var existingIdentitySystem = new ExistingIdentitySystem();
        if (existingIdentitySystem.PasswordSignIn(userId, password) == false)
        {
            throw new InvalidOperationException();
        }

        // ExistingUser
        var existingUser = existingIdentitySystem.GetUserById(userId);
        if (existingUser == null) throw new InvalidOperationException();

        // ApplicationUser
        var applicationIdentity = new ClaimsIdentity(IdentityOptions.Current.ApplicationCookieAuthenticationScheme, ClaimTypes.Name, ClaimTypes.Role);
        applicationIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, existingUser.Id));
        applicationIdentity.AddClaim(new Claim(ClaimTypes.Name, existingUser.Name));

        var applicationUser = new ClaimsPrincipal(applicationIdentity);

        // Cookie
        await this.HttpContext.Authentication.SignInAsync(IdentityOptions.Current.ApplicationCookieAuthenticationScheme, applicationUser);
        await this.HttpContext.Authentication.SignOutAsync(IdentityOptions.Current.ExternalCookieAuthenticationScheme);

        // Return
        return Redirect(returnUrl);
    }
}

使用

完成開發步驟後,當系統執行到打上[Authorize]標簽的Controller或是Action時,就會跳轉到Login頁面。

public class HomeController : Controller
{
    [Authorize]
    public IActionResult Contact()
    {
        ViewData["Message"] = "Hello " + User.Identity.Name + "!";

        return View();
    }
}

使用01

使用02

使用 - Facebook Authentication

在Login頁面,當使用者選擇使用Facebook驗證,系統會跳轉到Facebook頁面進行驗證與授權。完成驗證授權的相關步驟後,使用者就可以進入被打上[Authorize]標簽的Controller或是Action。

使用Facebook01

使用Facebook02

使用Facebook03

使用 - Password Authentication

在Login頁面,當使用者選擇使用Password驗證,系統會使用Login頁面上輸入的賬號密碼來進行驗證與授權。完成驗證授權的相關步驟後,使用者就可以進入被打上[Authorize]標簽的Controller或是Action。

使用Password01

使用Password02

範例

範常式序代碼:下載地址


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

-Advertisement-
Play Games
更多相關文章
  • 基本信息:節點一:ip:192.168.8.166 主機名:hadrtest01節點二:ip:192.168.8.250 主機名:hadrtest02 1、兩節點分別安裝rsh,rsh-server包是否已經安裝 yum -y install rsh rsh-server 2、修改/etc/xine
  • 本文轉載自:http://www.ibm.com/developerworks/cn/linux/1407_liuming_init1/index.html (本人學習使用添加了個人成分) 近年來,Linux 系統的 init 進程經歷了兩次重大的演進,傳統的 sysvinit 已經淡出歷史舞臺,新
  • 下麵貼出的是centos6.5 /etc/rc.sysinit文件內容 #!/bin/bash # # /etc/rc.d/rc.sysinit - run once at boot time # # Taken in part from Miquel van Smoorenburg's bchec
  • 在CentOS 6.5上安裝python2.7
  • linux與Windows共用文件配置: 1.進入超級用戶:$su root 2.啟動tftp伺服器:#netstat -a | grep tftp,出現如圖所示的消息表示tftp伺服器已安裝成功; 3.安裝NFS伺服器: #rpm –q nfs-utils,如果有下圖的信息出現說明已經安裝: 4.
  • 在項目開發的過程中,發現程式總是死在判斷DMA一次傳輸是否完成這個標誌位上。進一步回退分析,發現是在I2C讀的過程中,有使用到DMA去取外部I2C設備的data。 但是data並沒有讀完,Data為32bits,DMA在讀到18bits時,就出現讀不到data bit了。導致I2C硬體模塊不能進一步
  • WM_DEVICECHANGE消息 查閱MSDN得知: The framework calls this member function to notify an application or device driver of a change to the hardware configurati
  • 關於如下程式結構的描述中,哪一項是正確的? for ( ; ; ) { 迴圈體; //何問起 } a) 不執行迴圈體b) 一直執行迴圈體,即死迴圈c) 執行迴圈體一次d) 程式不符合語法要求 答案:http://hovertree.com/tiku/bjaf/9eclwqps.htm 首頁:http
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...