zoukankan      html  css  js  c++  java
  • [ASP.NET] ASP.NET Identity 中 ClaimsIdentity 解析

    各位好 : ) 

    最近筆者在嘗試改用ASP.NET Identity做為新系統的認證方式,發現到網路上給的資訊,不是很完整,所以做為一個工程屍,為了避免大家遇到一樣的問題。特地將一些有趣的地方記錄下來

    首先如果你是舊的專案,想要用ASP.NET Identity ,你必需要利用NuGet安裝以下幾個套件

    Microsoft.Owin.Host.SystemWeb

    Microsoft.AspNet.Identity.Owin

    接下來,我是在App_Start資料夾中加入Startup.cs檔,加入以下程式碼 (這裡是直接參考有用Identity的專案中的設定,但專案中是有將Startup.cs拆成兩個class ,這裡我僅用一個class檔)

    public void Configuration(IAppBuilder app)
    {
    ConfigureAuth(app);
    }
    public void ConfigureAuth(IAppBuilder app)
    {
    // Cookie Auth
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Home/Index")
    });
    // Use a cookie to temporarily store information about a user logging in with a third party login provider
    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ApplicationCookie);
    }

    再來微調一下專案中的Web.config檔

    <system.web>
    <authentication mode="None" />
      ------------------------------------------------------
    <system.webServer>
    <modules>
    <remove name="FormsAuthenticationModule" />
    </modules>

    在實際要進行登入時,有二種寫法。二種都是可以的,但接下來我會講到幾個點要注意

    //AuthenticationManager的獲取方式

    HttpContext.GetOwinContext().Authentication;

    //清除先前的登錄資訊

    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);

    //第一種

    IList<Claim> claims = new List<Claim>();

    claims.Add(new Claim(ClaimTypes.NameIdentifier, Request["userName"].ToString()));

    claims.Add(new Claim(ClaimTypes.Name, Request["userName"].ToString()));

    claims.Add(new Claim(ClaimTypes.Role, "Users"));

    ClaimsIdentity identity = new ClaimsIdentity(claims,

    DefaultAuthenticationTypes.ApplicationCookie);

    //第二種

    ClaimsIdentity claimsIdentity = new ClaimsIdentity(DefaultAuthenticationTypes.ApplicationCookie,ClaimTypes.NameIdentifier, ClaimTypes.Role);

    claimsIdentity.AddClaim(new Claim( ClaimTypes.NameIdentifier, "MyCustomID"));

    claimsIdentity.AddClaim(new Claim(ClaimTypes.Name, "MyCustomUser"));

    claimsIdentity.AddClaim(new Claim(
    ClaimTypes.NameIdentifier, Request["userName"].ToString(),
    "http://www.w3.org/2001/XMLSchema#string"));


    claimsIdentity.AddClaim(
    new Claim("http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider",
    "My Identity", "http://www.w3.org/2001/XMLSchema#string"));

    //這裡強烈建議用第二種的寫法, 原因是如果你的頁面有利用antiforgerytoken 來防CSRF攻擊時,第一種寫法會產生錯誤

    //但如果用第二種寫法,並加上identityprovider 這一個Claim 。就能正常使用了,不過在本篇最下方也有提到,可以透過Global.asax.cs加入參數設定,如果是透過Global.asax.cs的話,則以上兩種寫法都是沒有問題的 : )

    //登錄

    AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = true },identity);

    -----------------------------重點來了-------------------------------

    我在找資料時發現在StackOverFlow上有的回應居然是錯的…

    比如說像以下這篇

    http://stackoverflow.com/questions/18801120/where-is-microsoft-aspnet-identity-owin-authenticationmanager-in-asp-net-identit

    private async Task SignInAsync(ApplicationUser user, bool isPersistent) {

    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);

    var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);

    AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);

    }

    其實他提到的並沒有很完整,問題在哪裡呢?問題在於我們的Startup.cs中

    app.UseCookieAuthentication(new CookieAuthenticationOptions

    {

    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,

    LoginPath = new PathString("/Home/Index")

    });

    // Use a cookie to temporarily store information about a user logging in with a third party login provider

    //其實這一段內部實作來說跟上面是一樣的

    app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

    其實ClaimsIdentity 最後是會用粗體的地方做為Cookie的名稱,而也是因為這樣,如果你在SignOut的方法裡指定的名稱跟Startup.cs中設定的不一樣。會導致你無法正常的登出先前使用者的資訊喔!(很重要)

    有興趣可以參考這篇

    CookieAuthenticationMiddelware 对cookie的加密方式

    至於剛剛提到的Startup.cs ,嚴格來說其實app.UseExternalSignInCookie與app.UseCookieAuthentication只要選一種實作就可以了。參考一下UseExternalSignInCookie原始碼會發現其實他做的事情真的跟UseCookieAuthentication是差不多的

    public static void UseExternalSignInCookie(this IAppBuilder app, string externalAuthenticationType) {

    if (app == null) {

    throw new ArgumentNullException("app");

    }

    app.SetDefaultSignInAsAuthenticationType(externalAuthenticationType);

    app.UseCookieAuthentication(new CookieAuthenticationOptions {

    AuthenticationType = externalAuthenticationType,

    AuthenticationMode = AuthenticationMode.Passive,

    CookieName = CookiePrefix + externalAuthenticationType,

    ExpireTimeSpan = TimeSpan.FromMinutes(5),

    });

    }

    出處

    根據上面我們提到的CookieName設定,也可以知道我們如果是利用ClaimsIdentity要做登入時,CookieName也要跟Startup.cs設定的一樣,不然你會發現,明明程式碼都是對的,為什麼就是登入不了 (  ̄ c ̄)y▂ξ

    ClaimsIdentity claimsIdentity = new ClaimsIdentity(DefaultAuthenticationTypes.ApplicationCookie,ClaimTypes.NameIdentifier, ClaimTypes.Role);

    另外,如果又不小心遇到AntiForgery錯誤的話 (這是微軟提供一種防CSRF攻擊的方法)

    可以在Global.asax.cs檔中在Appliccation_Start加入這段。ClaimTypes就端看你的ClaimsIdentity有什麼樣的Types能用

    AntiForgeryConfig.UniqueClaimTypeIdentifier  = ClaimTypes.NameIdentifier;

    以上是簡單的ClaimsIdentity心得,我們下回見 : )

    參考 : 

    http://www.cnblogs.com/jesse2013/p/aspnet-identity-claims-based-authentication-and-owin.html#protectcookie

    https://github.com/MohammadYounes/MVC5-MixedAuth/issues/20

    http://dotnetcodr.com/2013/02/11/introduction-to-claims-based-security-in-net4-5-with-c-part-1/

    http://stackoverflow.com/questions/19977833/anti-forgery-token-issue-mvc-5

  • 相关阅读:
    zeplin使用教程
    如何卸载命令行全局安装的包
    webstrom快捷键
    更新npm至最新版本
    mac环境下安装react项目环境
    横向滚动条布局
    JAVA语法基础——动手动脑
    JAVA语言课堂测试
    暑假第八周进度报告
    暑假第七周进度报告
  • 原文地址:https://www.cnblogs.com/KingJaja/p/5234290.html
Copyright © 2011-2022 走看看