当前位置:网站首页>Using identity framework to realize JWT identity authentication and authorization in.Net 6.0
Using identity framework to realize JWT identity authentication and authorization in.Net 6.0
2022-07-28 07:34:00 【Dotnet cross platform】
Original author :Sarathlal Saseendran
Link to the original text :https://www.c-sharpcorner.com/article/jwt-authentication-and-authorization-in-net-6-0-with-identity-framework/
translate : The wolf at the end of the desert ( Google translation blessing )
Introduce
Microsoft was founded 2021 year 11 Month issued .NET 6.0. I am already in C# Corner[1] I wrote several articles about JWT Identity authentication articles . because .NET 6.0 Some major changes have been made , So I decided to write an article about using .NET 6.0 Version in progress JWT Identity Authentication The article . We will use Microsoft Identity Framework to store user and role information .
Authentication( Identity Authentication ) It is the process of verifying user credentials , and Authorization( to grant authorization ) It is the process of checking the user's permission to access specific modules in the application . In this paper , We will learn how to implement JWT Identity authentication to protect ASP.NET Core Web API Applications . We will also learn how to ASP.NET Core Authorization is used in to provide access to various functions of the application . We store user credentials in SQL Server In the database ( notes : You can use MySQL、PostgreSQL And other relational databases ), We will use EF Core The framework and Identity Framework for database operations .
JSON Web Token (JWT) It's an open standard (RFC 7519), It defines a compact and self-contained way , Use JSON Object is used to securely transmit information between parties . This information can be verified and trusted , Because it's digitally signed .JWT You can use the key ( Use HMAC Algorithm ) Or use RSA or ECDSA The public key / The private key pair is signed .
In its compact form ,JSON Web Tokens It's made up of three parts , By point (.) Separate , They are :
Header( title )
Payload( Payload )
Signature( Signature )
therefore ,JWT The format is usually as follows :
xxxx.yyyy.zzzz of JSON Web token For more details , Please refer to the link below .
https://jwt.io/introduction/[2]
Use Visual Studio 2022 establish ASP.NET Core Web API
We need to Visual Studio 2022 To create .NET 6.0 Applications . We can Visual Studio 2022 Choose from ASP.NET Core Web API Templates .

We can choose a suitable name for our project and choose .NET 6.0 frame .

Our new project will be created later .
We must put the following 4 Install libraries into new projects .
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
Microsoft.AspNetCore.Identity.EntityFrameworkCore
Microsoft.AspNetCore.Authentication.JwtBearer
You can use NuGet Package manager to install the above packages .
We can use the following values to change appsettings.json. It has functions for JWT Database connection details and other details of identity authentication .
appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"ConnStr": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=JWTAuthDB;Integrated Security=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
},
"JWT": {
"ValidAudience": "http://localhost:4200",
"ValidIssuer": "http://localhost:5000",
"Secret": "JWTAuthenticationHIGHsecuredPasswordVVVp1OH7Xzyr"
}
} We can create a new folder Auth And in Auth Create under folder ApplicationDbContext Class and add the following code . We will be in Auth Add all classes related to identity authentication under the folder .
ApplicationDbContext.cs
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
namespace IdentityDemo.Auth
{
public class ApplicationDbContext : IdentityDbContext<IdentityUser>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
}
} Create a static class UserRoles And add the following values .
UserRoles.cs
namespace IdentityDemo.Auth
{
public static class UserRoles
{
public const string Admin = "Admin";
public const string User = "User";
}
} We added two constant values Admin and User As a role . You can add as many roles as you need .
Create a class RegisterModel, New users register with .
RegisterModel.cs
using System.ComponentModel.DataAnnotations;
namespace IdentityDemo.Auth
{
public class RegisterModel
{
[Required(ErrorMessage = " The username cannot be empty ")] public string? Username { get; set; }
[EmailAddress]
[Required(ErrorMessage = " The message cannot be empty ")]
public string? Email { get; set; }
[Required(ErrorMessage = " The password cannot be empty ")] public string? Password { get; set; }
}
} Create a class LoginModel For user login .
LoginModel.cs
using System.ComponentModel.DataAnnotations;
namespace IdentityDemo.Auth
{
public class LoginModel
{
[Required(ErrorMessage = " The username cannot be empty ")] public string? Username { get; set; }
[Required(ErrorMessage = " The password cannot be empty ")] public string? Password { get; set; }
}
} We can create one Response class , Used to return the response value after user registration and user login . If the request fails , It also returns an error message .
Response.cs
namespace IdentityDemo.Auth
{
public class Response
{
public string? Status { get; set; }
public string? Message { get; set; }
}
} We can do it in Controllers Create a API controller AuthenticateController And add the following code .
AuthenticateController.cs
using IdentityDemo.Auth;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
namespace IdentityDemo.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class AuthenticateController : ControllerBase
{
private readonly UserManager<IdentityUser> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
private readonly IConfiguration _configuration;
public AuthenticateController(
UserManager<IdentityUser> userManager,
RoleManager<IdentityRole> roleManager,
IConfiguration configuration)
{
_userManager = userManager;
_roleManager = roleManager;
_configuration = configuration;
}
[HttpPost]
[Route("login")]
public async Task<IActionResult> Login([FromBody] LoginModel model)
{
var user = await _userManager.FindByNameAsync(model.Username);
if (user != null && await _userManager.CheckPasswordAsync(user, model.Password))
{
var userRoles = await _userManager.GetRolesAsync(user);
var authClaims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
foreach (var userRole in userRoles)
{
authClaims.Add(new Claim(ClaimTypes.Role, userRole));
}
var token = GetToken(authClaims);
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo
});
}
return Unauthorized();
}
[HttpPost]
[Route("register")]
public async Task<IActionResult> Register([FromBody] RegisterModel model)
{
var userExists = await _userManager.FindByNameAsync(model.Username);
if (userExists != null)
return StatusCode(StatusCodes.Status500InternalServerError,
new Response { Status = "Error", Message = " The user already exists !" });
IdentityUser user = new()
{
Email = model.Email,
SecurityStamp = Guid.NewGuid().ToString(),
UserName = model.Username
};
var result = await _userManager.CreateAsync(user, model.Password);
if (!result.Succeeded)
return StatusCode(StatusCodes.Status500InternalServerError,
new Response
{
Status = "Error", Message = " Failed to create user ! Please check and try again ."
});
return Ok(new Response { Status = "Success", Message = " New user succeeded !" });
}
[HttpPost]
[Route("register-admin")]
public async Task<IActionResult> RegisterAdmin([FromBody] RegisterModel model)
{
var userExists = await _userManager.FindByNameAsync(model.Username);
if (userExists != null)
return StatusCode(StatusCodes.Status500InternalServerError,
new Response { Status = "Error", Message = " The user already exists !" });
IdentityUser user = new()
{
Email = model.Email,
SecurityStamp = Guid.NewGuid().ToString(),
UserName = model.Username
};
var result = await _userManager.CreateAsync(user, model.Password);
if (!result.Succeeded)
return StatusCode(StatusCodes.Status500InternalServerError,
new Response
{
Status = "Error", Message = " Failed to create user ! Please check and try again ."
});
if (!await _roleManager.RoleExistsAsync(UserRoles.Admin))
await _roleManager.CreateAsync(new IdentityRole(UserRoles.Admin));
if (!await _roleManager.RoleExistsAsync(UserRoles.User))
await _roleManager.CreateAsync(new IdentityRole(UserRoles.User));
if (await _roleManager.RoleExistsAsync(UserRoles.Admin))
{
await _userManager.AddToRoleAsync(user, UserRoles.Admin);
}
if (await _roleManager.RoleExistsAsync(UserRoles.Admin))
{
await _userManager.AddToRoleAsync(user, UserRoles.User);
}
return Ok(new Response { Status = "Success", Message = " New user succeeded !" });
}
private JwtSecurityToken GetToken(List<Claim> authClaims)
{
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Secret"]));
var token = new JwtSecurityToken(
issuer: _configuration["JWT:ValidIssuer"],
audience: _configuration["JWT:ValidAudience"],
expires: DateTime.Now.AddHours(3),
claims: authClaims,
signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
);
return token;
}
}
} We added three methods to the controller class login、register and register-admin``.register and register-admin Almost the same , but register-admin Method will be used to create a with Admin Users of roles . stay login In the method , We returned a JWT token.
stay .NET 6.0 in , Microsoft deleted Startup class ( notes : You can resume using this method ), Just keep Program class . We have to Program Class to define all dependency injection and other configurations .
Program.cs
using IdentityDemo.Auth;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
ConfigurationManager configuration = builder.Configuration;
// Add services to the container.
// For Entity Framework
builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(configuration.GetConnectionString("ConnStr")));
// For Identity
builder.Services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Adding Authentication
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
// Adding Jwt Bearer
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = configuration["JWT:ValidAudience"],
ValidIssuer = configuration["JWT:ValidIssuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JWT:Secret"]))
};
});
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
// Authentication & Authorization
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();We must create the required databases and tables before running the application . Because we use Entity Framework (EF Core), We can use the following database migration command and package manager console to create a migration script :
add-migration Initial

Use the following commands to create databases and tables :
update-database

If you use SQL Server Object explorer Check the database , You can see that the following database tables are created inside the database :

In the process of database migration , by User、Role and Claims Created 7 A watch . This is for Identity frame .
ASP.NET Core Identity It's a membership system , Allows you to add login functionality to your application . Users can create accounts and use User name and password Sign in , You can also use External login provider , for example Facebook、Google、Microsoft Account、Twitter etc. .
You can use ASP.NET Core Identity Configure to use SQL Server Database to store user names 、 Password and profile data . perhaps , You can use your own persistent storage to store data in another persistent storage , for example Azure Table is stored .
We can do it in WeatherForecast Add in controller Authorize attribute .

We can run the application and try from Postman Tool access WeatherForecastController Medium get Method .

We received 401 Unauthorized error . because , We have added Authorize attribute . We must provide a valid through the request header token To access this controller and the methods within the controller .
We can do it in AuthenticateController Create a new user using the registration method .

We take the original JSON Format provides input data .
We can use the above user credentials to log in and obtain a valid JWT token.

After successfully logging in with the above credentials , We received a token.
We can use https://jwt.io[3] Site decode token And view the statement and other information .

We can add the above... In the authorization tab token Value as Bearer token Pass on , And call... Again WeatherForecastController Of get Method .

This time, , We successfully received the value from the controller .
We can use role-based authorization to change WeatherForecastController.

Now? , Only with administrator (Admin) Users of the role can access this controller and method .
We can try in Postman Use the same... Again in the tool token visit WeatherForecastController.

We have received it now 403 Reject mistakes instead of 401. Even if we pass a valid token, We also don't have enough permissions to access the controller . To access this controller , The user must have Admin Role permissions . The current user is an ordinary user , There is no Admin Role permissions .
We can create one with Admin New users with role permissions . We've been AuthenticateController There is a method in register-admin For the same purpose .

We can use these new user credentials to log in and get a new token. If you are right about token decode , You can see that the role has been added to token in .

We can use this token Not old token To visit WeatherForecastController.

Now we have succeeded from WeatherForecastController We got the data from .
Conclusion
In this article , We learned how to .NET 6.0 ASP.NET Core Web API Created in the application JSON Web token, And use this token Authentication and authorization . We created two users , One doesn't have any roles , One has Admin role . We applied authentication and authorization at the controller level , And I saw the different behaviors of these two users .
In this paper, the source code :IdentityDemo[4]
Reference material
[1]
C# Corner: https://www.c-sharpcorner.com/
[2]https://jwt.io/introduction/: https://jwt.io/introduction/
[3]https://jwt.io: https://jwt.io
[4]IdentityDemo: https://github.com/dotnet9/ASP.NET-Core-Test/tree/master/src/IdentityDem
边栏推荐
猜你喜欢

Soft exam certificate can be used like this! Get a certificate = get a professional title?
![[solution] visual full link log tracking - log tracking system](/img/0c/f93c7d31e01257c5dee7d292ac7d84.jpg)
[solution] visual full link log tracking - log tracking system

删除链表中的节点——每日一题

The cornerstone of EMC - complete knowledge of electromagnetic compatibility filtering!

EMC问题的根源在哪?

DNA修饰金属锇Os纳米颗粒OsNPS-DNA|DNA修饰金属铱纳米颗粒IrNPS-DNA
![[JVM optimization] online JVM tuning practice](/img/e3/5fa128805af0ca03f0b6715b78d398.jpg)
[JVM optimization] online JVM tuning practice

Disassemble Huawei switches and learn Basic EMC operations

Isolation level RR, gap lock, unreal reading

guava之限流RateLimiter
随机推荐
牛客Mysql——SQL必知必会
On deep paging
Overview of distributed system development
Eventbus of guava
Advanced pointer practice
DNA修饰金属锇Os纳米颗粒OsNPS-DNA|DNA修饰金属铱纳米颗粒IrNPS-DNA
VCF file production
【解决方案】可视化全链路日志追踪-日志追踪系统
Current limiting ratelimiter of guava
浅谈深分页问题
Database-Trivial
The "nuclear bomb level" log4j vulnerability is still widespread and has a continuing impact
cdn.jsdelivr.net不可用,该怎么办
再次出现用户净流失,大失颜面的中国移动推出超低价套餐争取用户
Big talk persistence and redolog
EMC rectification ideas
Not used for the longest time recently
How low-end computers learn secrets in depth - using the mistgpu computing platform
Why is ESD protection so important for integrated circuits? How to protect?
Deeply analyze the implementation of singleton mode