溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何使ASP.NETCore和ASP.NETFramework共享身份驗證

發(fā)布時間:2021-09-16 13:47:55 來源:億速云 閱讀:99 作者:柒染 欄目:開發(fā)技術

如何使ASP.NETCore和ASP.NETFramework共享身份驗證,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

.NET Core 已經(jīng)熱了好一陣子,1.1版本發(fā)布后其可用性也越來越高,開源、組件化、跨平臺、性能優(yōu)秀、社區(qū)活躍等等標簽再加上“微軟爸爸”主推和大力支持,盡管現(xiàn)階段對比.net framework還是比較“稚嫩”,但可以想象到它光明的前景。作為.net 開發(fā)者你是否已經(jīng)開始嘗試將項目遷移到.net core上?這其中要解決的一個較大的問題就是如何讓你的.net core和老.net framework站點實現(xiàn)身份驗證兼容!

1、第一篇章

我們先來看看.net core中對identity的實現(xiàn),在Startup.cs的Configure中配置Cookie認證的相關屬性

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
  app.UseCookieAuthentication(new CookieAuthenticationOptions
  {
    AuthenticationScheme = "test",
    CookieName = "MyCookie"
  });
}

Controller

public IActionResult Index()
{
  return View();
}

public IActionResult Login()
{
  return View();
}

[HttpPost]
public async Task<IActionResult> Login(string name)
{
  var identity = new ClaimsIdentity(
          new List<Claim>
          {
          new Claim(ClaimTypes.Name,name, ClaimValueTypes.String)
          },
          ClaimTypes.Authentication,
          ClaimTypes.Name,
          ClaimTypes.Role);
  var principal = new ClaimsPrincipal(identity);
  var properties = new AuthenticationProperties { IsPersistent = true };

  await HttpContext.Authentication.SignInAsync("test", principal, properties);

  return RedirectToAction("Index");
}

login 視圖

<!DOCTYPE html>
<html>
<head>
  <title>登錄</title>
</head>
<body>
  <form asp-controller="Account" asp-action="Login" method="post">
    <input type="text" name="name" /><input type="submit" value="提交" />
  </form>
</body>
</html>

index 視圖

<!DOCTYPE html>
<html>
<head>
 <title>歡迎您-@User.Identity.Name</title>
</head>
<body>
  @if (User.Identity.IsAuthenticated)
  {
    <p>登錄成功!</p>
  }
</body>
</html>

下面是實現(xiàn)效果的截圖:

如何使ASP.NETCore和ASP.NETFramework共享身份驗證

如何使ASP.NETCore和ASP.NETFramework共享身份驗證

ok,到此我們用.net core比較簡單地實現(xiàn)了用戶身份驗證信息的保存和讀取。

接著思考,如果我的.net framework項目想讀取.net core項目保存的身份驗證信息應該怎么做?

要讓兩個項目都接受同一個Identity至少需要三個條件:

  • CookieName必須相同。

  • Cookie的作用域名必須相同。

  • 兩個項目的Cookie認證必須使用同一個Ticket。

首先我們對.net core的Cookie認證添加domain屬性和ticket屬性

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
  var protectionProvider = DataProtectionProvider.Create(new DirectoryInfo(@"C:\keyPath\"));
  var dataProtector = protectionProvider.CreateProtector("MyCookieAuthentication");
  var ticketFormat = new TicketDataFormat(dataProtector);

  app.UseCookieAuthentication(new CookieAuthenticationOptions
  {
    AuthenticationScheme = "test",
    CookieName = "MyCookie",
    CookieDomain = "localhost",
    TicketDataFormat = ticketFormat
  });
}

此時我們在.net core 項目中執(zhí)行用戶登錄,程序會在我們指定的目錄下生成key.xml

如何使ASP.NETCore和ASP.NETFramework共享身份驗證

我們打開文件看看程序幫我們記錄了那些信息

<?xml version="1.0" encoding="utf-8"?>
<key id="eb8b1b59-dbc5-4a28-97ad-2117a2e8f106" version="1">
 <creationDate>2016-12-04T08:27:27.8435415Z</creationDate>
 <activationDate>2016-12-04T08:27:27.8214603Z</activationDate>
 <expirationDate>2017-03-04T08:27:27.8214603Z</expirationDate>
 <descriptor deserializerType="Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer, Microsoft.AspNetCore.DataProtection, Version=1.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60">
  <descriptor>
   <encryption algorithm="AES_256_CBC" />
   <validation algorithm="HMACSHA256" />
   <masterKey p4:requiresEncryption="true" xmlns:p4="http://schemas.asp.net/2015/03/dataProtection">
    <value>yHdMEYlEBzcwpx0bRZVIbcGJ45/GqRwFjMfq8PJ+k7ZWsNMic0EMBgP33FOq9MFKX0XE/a1plhDizbb92ErQYw==</value>
   </masterKey>
  </descriptor>
 </descriptor>
</key>

ok,接下來我們開始配置.net framework項目,同樣,在Startup.cs中配置Cookie認證的相關屬性。

public partial class Startup
{
  public void Configuration(IAppBuilder app)
  {
    var protectionProvider = DataProtectionProvider.Create(new DirectoryInfo(@"C:\keyPath\"));
    var dataProtector = protectionProvider.CreateProtector("MyCookieAuthentication");
    var ticketFormat = new AspNetTicketDataFormat(new DataProtectorShim(dataProtector));
      
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
      AuthenticationType = "test",
      CookieName = "MyCookie",
      CookieDomain = "localhost",
      TicketDataFormat = ticketFormat
    });
  }
}

view

<!DOCTYPE html>
<html>
<head>
  <title>.net framewor歡迎您-@User.Identity.Name</title>
</head>
<body>
  @if (User.Identity.IsAuthenticated)
  {
    <p>.net framework登錄成功!</p>
  }
</body>
</html>

寫法和.net core 基本上是一致的,我們來看下能否成功獲取用戶名:

如何使ASP.NETCore和ASP.NETFramework共享身份驗證

反之在.net framework中登錄在.net core中獲取身份驗證信息的方法是一樣的,這里就不重復寫了。

然而,到此為止事情就圓滿解決了嗎?很遺憾,麻煩才剛剛開始!

--------------------------------------------------------------------------------

2、第二篇章

如果你的子項目不多,也不復雜的情況下,新增一個.net core 站點,然后適當修改以前的.net framework站點,上述實例確實能夠滿足需求??墒侨绻愕淖诱军c足夠多,或者項目太過復雜,牽扯到的業(yè)務過于龐大或重要,這種情況下我們通常是不愿意動老項目的?;蛘哒f我們沒有辦法將所有的項目都進行更改,然后和新增的.net core站點同時上線,如果這么做了,那么更新周期會拉的很長不說,測試和更新之后的維護階段壓力都會很大。所以我們必須要尋找到一種方案,讓.net core的身份驗證機制完全迎合.net framwork。

因為.net framework 的cookie是對稱加密,而.net core是非對稱加密,所以要在.net core中動手的話必須要對.net core 默認的加密和解密操作進行攔截,如果可行的話最好的方案應該是將.net framework的FormsAuthentication類移植到.net core中。但是用reflector看了下,牽扯到的代碼太多,剪不斷理還亂,github上也沒找到其源碼,瞎忙活了一陣之后終于感慨:臣妾做不到(>﹏< )。

Cookie認證的相關屬性

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
  AuthenticationScheme = "test",
  CookieName = "MyCookie",
  CookieDomain = "localhost",
  TicketDataFormat = new FormsAuthTicketDataFormat("")
});

FormsAuthTicketDataFormat

public class FormsAuthTicketDataFormat : ISecureDataFormat<AuthenticationTicket>
{
  private string _authenticationScheme;

  public FormsAuthTicketDataFormat(string authenticationScheme)
  {
    _authenticationScheme = authenticationScheme;
  }

  public AuthenticationTicket Unprotect(string protectedText, string purpose)
  {
    var formsAuthTicket = GetFormsAuthTicket(protectedText);
    var name = formsAuthTicket.Name;
    DateTime issueDate = formsAuthTicket.IssueDate;
    DateTime expiration = formsAuthTicket.Expiration;

    var claimsIdentity = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, name) }, "Basic");
    var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);

    var authProperties = new Microsoft.AspNetCore.Http.Authentication.AuthenticationProperties
    {
      IssuedUtc = issueDate,
      ExpiresUtc = expiration
    };
    var ticket = new AuthenticationTicket(claimsPrincipal, authProperties, _authenticationScheme);
    return ticket;
  }

  FormsAuthTicket GetFormsAuthTicket(string cookie)
  {
    return DecryptCookie(cookie).Result;
  }

  async Task<FormsAuthTicket> DecryptCookie(string cookie)
  {
    HttpClient _httpClient = new HttpClient();
    var response = await _httpClient.GetAsync("http://192.168.190.134/user/getMyTicket?cookie={cookie}");
    response.EnsureSuccessStatusCode();
    return await response.Content.ReadAsAsync<FormsAuthTicket>();
  }
}

FormsAuthTicket

public class FormsAuthTicket
{
  public DateTime Expiration { get; set; }
  public DateTime IssueDate { get; set; }
  public string Name { get; set; }
}

以上實現(xiàn)了對cookie的解密攔截,然后通過webapi從.net framework獲取ticket

[Route("getMyTicket")]
public IHttpActionResult GetMyTicket(string cookie)
{
  var formsAuthTicket = FormsAuthentication.Decrypt(cookie);
  return Ok(new { formsAuthTicket.Name, formsAuthTicket.IssueDate, formsAuthTicket.Expiration });
}

有了webapi這條線,解密解決了,加密就更簡單了,通過webapi獲取加密后的cookie,.net core要做的只有一步,保存cookie就行了

[HttpPost]
public async Task<IActionResult> Login(string name)
{
  HttpClient _httpClient = new HttpClient();
  var response = await _httpClient.GetAsync($"http://192.168.190.134/user/getMyCookie?name={name}");
  response.EnsureSuccessStatusCode();

  string cookieValue = (await response.Content.ReadAsStringAsync()).Trim('\"');
  CookieOptions options = new CookieOptions();
  options.Expires = DateTime.MaxValue;
  HttpContext.Response.Cookies.Append("MyCookie", cookieValue, options);

  return RedirectToAction("Index");
}

webapi獲取cookie

[Route("getMyCookie")]
public string GetMyCookie(string name)
{
  FormsAuthentication.SetAuthCookie(name, false);
  return FormsAuthentication.GetAuthCookie(name, false).Value;
}

其余代碼不用做任何更改,ok,我們來測試一下

如何使ASP.NETCore和ASP.NETFramework共享身份驗證

ok,登錄成功,至此完成.net framework和.net core身份驗證的兼容。

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業(yè)資訊頻道,感謝您對億速云的支持。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI