Microsoft.AspNetCore.Authentication.Cookies from entry to mastery

Original text: Microsoft.AspNetCore.Authentication.Cookies from entry to mastery (1)

Microsoft.AspNetCore.Authentication.Cookies from entry to mastery (1)

catalog

‚Äč Microsoft.AspNetCore.Authentication.Cookies is a storage component. Its main function is to save the call back information of authorization authentication to the client through Cookie mechanism, which is similar to my previous article session based authentication in AspNetCore The HttpSession principle in is the same except that session based authentication in AspNetCore In this article, we do our own verification scheme, and we use Asp.Net Core only provides authentication scheme.

Start a Demo

Demo source address

1. Create a Razor Page Project: dotnet new razor -n CookieSample

2. Open Startup.cs Documents, adding certification codes

public void ConfigureServices(IServiceCollection services)
{
  	.......
    services.AddAuthentication()
        .AddCookie();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
	......
    app.UseAuthentication();
	......
}

In just a few lines of code, we added the authorization authentication function to the project. Let's see how to use the authorization authentication in the page

3. Open Index.cshtml.cs File, add our certification code

[Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]
public class IndexModel : PageModel
{
	public void OnGet()
}

With only one line of code, my page becomes a page that can only be accessed after authorization and authentication. Run the project to visit the page to see the effect.

4. Add the Login page and implement Login authentication on this page

When you open the Index page, you will find that it has been redirected to / Account/Login. At this time, this page is not available in our project. Now we create the Login page and add some Login codes. The so-called Login does not really verify user information from the database. Of course, the process of data validation should be before the operation. The Login here is to The information you want to save in the Cookie is passed to Asp.Net The core authenticates the component, and the component serializes the information into the Cookie, so it can be seen that Microsoft.AspNetCore.Authentication.Cookies just for storage

public class LoginModel : PageModel
{
    public void OnPost()
    {
    	//You may need to verify some information with data
    	......
    	//After the database is verified, we need to save some information to the Cookie
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name,"Tst")
        };
        var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
        await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));

    }
}

This is all the code of our Demo, isn't it very simple.

Make our Demo closer to the real project

Case needs

Usually our website will distinguish between the foreground and the background. What ordinary users can access is called the foreground, and what administrators can access is called the background.

Demo source address

1. We will make the transformation based on the previous Demo. Now our project is divided into two types of users and the pages accessed by each type of user are not the same.

2. Let's create a page that administrators can access: /Admin/Index , now we have two pages for two types of users to visit, but we only have one Login page, so how can we make two types of users share one Login page?

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    ......
    services.AddAuthentication()
       	.AddCookie()
        .AddCookie("Admin","Admin",options=>{}); 
    ......
}

In the above code, I added an Admin authentication scheme for the administrator to access and explicitly set the authentication scheme in the / Admin/Index page:

/Admin/Index

[Authorize(AuthenticationSchemes = "Admin")]
public class IndexModel : PageModel{}

3. Now let's modify the Login page code. We need to do different authentication logins according to the authentication scheme. The purpose is to generate authentication cookie information

public class LoginModel : PageModel
{
	//Save authentication scheme and friendly display name
    [BindProperty]
    public IDictionary<string, string> Schemes { get; set; } = new Dictionary<string, string>();
	
	//Page we want to jump to after authentication
    [BindProperty]
    public string RedirectToUrl { get; set; }

    IAuthenticationSchemeProvider _authenticationSchemeProvider;

    //Constructor injection method gets IAuthenticationSchemeprovider instance
    public LoginModel(IAuthenticationSchemeProvider authenticationSchemeProvider)
    {
        //You can also obtain the IAuthenticationSchemeprovider instance by searching from the service
        //_authenticationSchemeProvider = (IAuthenticationSchemeProvider)HttpContext.RequestServices.GetService(typeof(IAuthenticationSchemeProvider));
        _authenticationSchemeProvider = authenticationSchemeProvider;
    }
    public async Task OnGetAsync(string ReturnUrl)
    {
        RedirectToUrl = ReturnUrl;
        var authenticationSchemes = await _authenticationSchemeProvider.GetAllSchemesAsync();
        foreach (var item in authenticationSchemes)
        {
        	//If we do not set DisplayName, we will replace it with the authentication scheme name
            Schemes.Add(item.Name, item.DisplayName??item.Name);
        }
    }

    public IActionResult OnPost(string scheme,string redirectUrl)
    {
        var claims = new List<Claim>
        {
            new Claim(ClaimTypes.Name,scheme)
        };
        //Generate identity information of different authentication schemes
        var claimsIdentity = new ClaimsIdentity(claims, scheme);
        //Save authentication information to a cookie
        HttpContext.SignInAsync(scheme, new ClaimsPrincipal(claimsIdentity));
        return LocalRedirect(redirectUrl);
    }
}

Let's review what the code did:

First of all, we injected an instance of IAuthenticationSchemeProvider into the constructor, which is mainly used to obtain all authentication schemes.

Then, we will Post the selected authentication scheme and the address to jump to after authentication to the Login page (here you also need to submit the user name and password and other data validation). After verification, we will write some information into the Cookie.

Insert a little personal thought: someone might think that we can't do two projects? Can't we make microservices? My answer is no: because all the tutorials here are about Microsoft.AspNetCore.Authentication . the functions of cookies are explained. There are many ways to achieve authentication. Everyone will have their own ideas and implementation, but we only talk about Asp.Net Core provides things that are conducive to unification and reduce learning costs. Only when learning costs are reduced can we have time to innovate.

Requirement update: add expiration time for certification

The normal user authentication information is required to expire 10 minutes after the last access, while the administrator needs to expire 1 day after the last access.

public void ConfigureServices(IServiceCollection services)
{
    ......
    services.AddAuthentication()
        .AddCookie(options=>{
			options.SlidingExpiration = true;
			options.ExpireTimeSpan = TimeSpan.FromMinutes(10);
        })
        .AddCookie("Admin","Admin",options=>{
			options.SlidingExpiration = true;
			options.ExpireTimeSpan = TimeSpan.FromDays(1);
        }); 
    ......
}

We implement authorization expiration through two attributes

SlidingExpiration: by setting this parameter to Ture, the expiration time can be changed into rolling (sliding) expiration, that is, the expiration time can be recalculated according to the last access. Only when the sliding Cookie is set, our authentication information is more like a callback state.

ExpireTimeSpan: set expiration time

Requirement update: persistent Cookie required

In the above requirements, every time we close the browser, the state of the Cookie is lost, which is not in line with our requirements. Now let's modify to make the Cookie persistent in the client. Previous articles Understanding cookies We introduced how to make cookie s persistent. The principle is to explicitly set Expires and MaxAge.

public void ConfigureServices(IServiceCollection services)
{
    ......
    services.AddAuthentication()
        .AddCookie(options=>{
			options.SlidingExpiration = true;
			options.ExpireTimeSpan = TimeSpan.FromMinutes(10);
            //Here we set the Cookie Expiration time to 365 days. You can also set it through the MaxAge property. However, it should be noted that MaxAge will replace the Expiration value
            options.Cookie.Expiration = TimeSpan.FromDays(365);
            //options.Cookie.MaxAge = TimeSpan.FromDays(365);
        })
        .AddCookie("Admin","Admin",options=>{
			options.SlidingExpiration = true;
			options.ExpireTimeSpan = TimeSpan.FromDays(1);
            options.Cookie.Expiration = TimeSpan.FromDays(365);
        }); 
    ......
}

We only need one line of code to turn cookies into persistent cookies, but there is a problem. We set the authentication cookie of ordinary users to expire in 10 minutes, but set the cookie to 365 days (the authentication cookie and cookie here are one thing, the expiration of authentication cookie is verified by the authentication service, and the cookie itself is verified by the browser. If the browser thinks that the cookie is expired If the authentication service does not get the cookie information at all), when the interval between visits to the page is more than 10 minutes, the cookie will still fail. At this time, although the cookie value is still there, it is already meaningless data, so we will use these three values options.ExpireTimeSpan , options.Cookie.Expiration , options.Cookie.MaxAge It seems more reasonable to set the same.

summary

  1. We showed you how to use Cookie based authorization authentication in projects.
  2. We introduced how to configure the authentication scheme and the friendly prompt name of the authentication scheme, and how to obtain all the authentication schemes to display on the page.
  3. We introduced how to configure the sliding expiration time of authentication and how to configure persistent cookies.

To be continued

Tags: Session Database

Posted on Sat, 30 May 2020 00:05:13 -0400 by darkjedig