当前位置:网站首页>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
边栏推荐
- EMC's "don't come back until you rectify"
- 2018-cvpr-Gesture Recognition: Focus on the Hands
- Disassemble Huawei switches and learn Basic EMC operations
- LeNet5、AlexNet、VGGNet、ResNet
- MySQL基础知识学习(二)
- DNA脱氧核糖核酸修饰金属铂纳米颗粒PtNPS-DNA|科研试剂
- 牛客Mysql——SQL必知必会
- 软考证书还能这样用!拿到证书=获得职称?
- VCF file production
- How did tensor leak your memory / video memory
猜你喜欢

EMC之 “不整改好别回来了”

Learning to estimate 3D hand pose from single RGB image & amp notes

js二级联动院系

5g commercial third year: driverless "going up the mountain" and "going to the sea"

再次出现用户净流失,大失颜面的中国移动推出超低价套餐争取用户

Industry standards and certification of common electronic products

How did tensor leak your memory / video memory

DNA脱氧核糖核酸修饰金属铂纳米颗粒PtNPS-DNA|科研试剂

Map uses tuple to realize multiple value values

DNA修饰金属锇Os纳米颗粒OsNPS-DNA|DNA修饰金属铱纳米颗粒IrNPS-DNA
随机推荐
VCF file production
登录heroku出现 IP address mismatch的解决方案
Overview of distributed system development
移动端H5输入框调起手机软键盘,导致底部固定定位被顶起解决方法
Summary of RFID radiation test
项目经历总结
Current limiting ratelimiter of guava
常用电子产品行业标准及认证
How to understand CMS collector to reduce GC pause time
JS upload file method
Disassemble Huawei switches and learn Basic EMC operations
The "nuclear bomb level" log4j vulnerability is still widespread and has a continuing impact
Dynamic memory management knowledge points
ThreadLocal那些事
Short work priority SJF
Principle and configuration of redis master-slave replication
隔离级别RR、间隙锁、幻读
【干货】32个EMC标准电路分享!
build_ opencv.sh
EMC问题的根源在哪?