Details about ASP. NET Core and ASP. NET Framework shared identity authentication, asp. netframework
. NET Core has been popular for a while, and its availability is getting higher and higher after the 1.1 Release, open-source, componentized, cross-platform, excellent performance, active community, and so on, coupled with the "Microsoft Dad" main push and strong support, despite the current comparison. net framework is still relatively "immature", but we can imagine its bright future. Have you started to migrate your project to. net core as A. net developer? One of the major problems to be solved is how to make your. net core compatible with the old. net framework website for identity authentication!
1. Chapter 1
Let's take a look at the implementation of identity in. net core, and Configure Cookie authentication attributes in Configure of Startup. cs.
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 View
<! DOCTYPE html>
<html>
<head>
<title> Sign in </ title>
</ head>
<body>
<form asp-controller = "Account" asp-action = "Login" method = "post">
<input type = "text" name = "name" /> <input type = "submit" value = "submit" />
</ form>
</ body>
</ html>
index View
<! DOCTYPE html>
<html>
<head>
<title> Welcome-@ User.Identity.Name </ title>
</ head>
<body>
@if (User.Identity.IsAuthenticated)
{
<p> Sign in successfully! </ p>
}
</ body>
</ html>
Here are the results:
Ok, so far we use .net core to implement the saving and reading of user authentication information.
Then think about what should I do if my .net framework project wants to read the authentication information saved by the .net core project?
There are at least three requirements for two projects to accept the same Identity:
CookieName must be the same.
The domain name of the cookie must be the same.
Cookie authentication for both projects must use the same ticket.
First we add domain attribute and ticket attribute to cookie authentication of .net core
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
});
}
At this point we perform user login in the .net core project, and the program will generate key.xml in the directory we specified.
Let's open the file and see what information the program has recorded for us
<?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, next we start to configure the .net framework project. Similarly, configure the related attributes of cookie authentication in Startup.cs.
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>
Welcome to <title> .net framewor-@ User.Identity.Name </ title>
</ head>
<body>
@if (User.Identity.IsAuthenticated)
{
<p> The login of .net framework is successful! </ p>
}
</ body>
</ html>
The writing is basically the same as .net core. Let's see if we can successfully obtain the user name:
Conversely, the method of logging in to the .net core to obtain authentication information in the .net framework is the same, so I will not repeat it here.
However, has everything been resolved so far? Unfortunately, the trouble has just begun!
-------------------------------------------------- ------------------------------
Chapter Two
If you do not have many sub-projects and are not complicated, add a new .net core site, and then modify the previous .net framework site appropriately. The above examples can really meet the requirements. But if you have enough subsites, or the project is too complicated, and the business involved is too large or important, in this case we are usually reluctant to move the old project. In other words, we have no way to change all the projects and then go online at the same time as the new .net core site. If this is done, the update cycle will be very long. Not to mention, the pressure during the maintenance phase after testing and updating will be Great. So we have to find a solution to make the authentication mechanism of .net core fully meet the .net framwork.
Because .net framework's cookies are symmetric encryption, and .net core is asymmetric encryption, you must intercept the default encryption and decryption operations of .net core if you want to operate in .net core. If feasible, the best solution should be The .Net framework's FormsAuthentication class is ported to the .net core. But I looked at it with reflector, the code involved was too much, the cutting was still chaotic, and the source code was not found on github. After a long life, I finally sighed that the minister could not do it (> ﹏ <).
Related attributes of cookie authentication
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; }
}
The above implements the decryption interception of cookies, and then obtains the ticket from the .net framework through webapi
[Route("getMyTicket")]
public IHttpActionResult GetMyTicket(string cookie)
{
var formsAuthTicket = FormsAuthentication.Decrypt(cookie);
return Ok(new { formsAuthTicket.Name, formsAuthTicket.IssueDate, formsAuthTicket.Expiration });
}
With the webapi line, the decryption is solved, and the encryption is simpler. To obtain the encrypted cookie through webapi, there is only one step for the .net core to do, and save the 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 get cookie
[Route("getMyCookie")]
public string GetMyCookie(string name)
{
FormsAuthentication.SetAuthCookie(name, false);
return FormsAuthentication.GetAuthCookie(name, false).Value;
}
The rest of the code does not need to be changed, ok, let's test it
OK, login is successful, and the compatibility of .net framework and .net core authentication is completed. Hey, if the team of .net core can consider more compatibility issues in this regard, even a compromise solution can make developers more Motivate to do the migration.
The above is the entire content of this article. I hope it will be helpful to everyone's learning, and I hope everyone will support the helper's home.