程序地带

ASP.NET Core - JWT认证实现


一、JWT结构

 JWT介绍就太多了,这里主要关注下Jwt的结构。 


 Jwt中包含三个部分:Header(头部).Payload(负载).Signature(签名)


Header:描述 JWT 的元数据的JSON对象,如:


{"alg":"HS256","typ":"JWT"}

Payload:一个用来存放实际需要传递的数据的JSON 对象。如:


"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "admin",
"exp": 1610877510,
"iss": "cba",
"aud": "cba"
}
Signature:对前两部分(Header、Payload)的签名,防止数据篡改。
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

  JWT示例:


eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiYWRtaW4iLCJleHAiOjE2MTA4Nzc1MTAsImlzcyI6ImNiYSIsImF1ZCI6ImNiYSJ9.O9lbZwfqRuA6vKcRCfYieA1zLkTPppdSvTc8UzwCkNw
二、ASP.NET Core 使用JTW认证

 1、添加Nuget包引用:


dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

 2、定义一个JwtSettingDto结构,用于读取JWT配置信息


public class JwtSetting
{
/// <summary>
/// 发行者
/// </summary>
public string Issuer { get; set; }
/// <summary>
/// 受众
/// </summary>
public string Audience { get; set; }
/// <summary>
/// 秘钥
/// </summary>
public string SecretKey { get; set; }
/// <summary>
/// 过期时间
/// </summary>
public int AccessExpiration { get; set; }
/// <summary>
/// 刷新时间
/// </summary>
public int RefreshExpiration { get; set; }
}

 3、在appsetting.json配置文件中,添加jwt相关配置信息


"JWTSetting": {
"Issuer": "cba",
"Audience": "cba",
"SecretKey": "123456789abcdefghi",
"AccessExpiration": 60,
"RefreshExpiration": 80
}

 4、在Startup.cs 中启用Jwt认证


public void ConfigureServices(IServiceCollection services)
{
services.Configure<JwtSetting>(Configuration.GetSection("JWTSetting"));
var token = Configuration.GetSection("JWTSetting").Get<JwtSetting>();
//JWT认证
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(token.SecretKey)),
ValidIssuer = token.Issuer,
ValidAudience = token.Audience,
ValidateIssuer = false,
ValidateAudience = false
};
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseAuthentication();
app.UseAuthorization();
}

 5、实现认证控制器:


  a) 添加认证Dto


public class LoginDto
{
[Required]
public string Username { get; set; }
[Required]
public string Password { get; set; }
}

  b) 实现用户校验服务:默认实现:当用户密码都等于admin通过校验  


public interface IUserService
{
bool IsValid(LoginDto request);
}
public class UserService : IUserService
{
//本次,固定校验admin
public bool IsValid(LoginDto request)
{
return request.Password == request.Username && request.Username == "admin";
}
}

  c) 实现签发token的认证服务:  


//认证服务接口public interface IAuthenticateService
{
bool IsAuthenticated(LoginDto request, out string token);
}
//认证服务
public class TokenAuthenticationService : IAuthenticateService
{
private readonly IUserService _userService;
private readonly JwtSetting _jwtSetting;
public TokenAuthenticationService(IUserService userService, IOptions<JwtSetting> jwtSetting)
{
_userService = userService;
_jwtSetting = jwtSetting.Value;
}
public bool IsAuthenticated(LoginDto request, out string token)
{
token = string.Empty;
if (!_userService.IsValid(request))
return false;
var claims = new[] { new Claim(ClaimTypes.Name, request.Username) };
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSetting.SecretKey));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var jwtToken = new JwtSecurityToken(_jwtSetting.Issuer, _jwtSetting.Audience, claims, expires: DateTime.Now.AddMinutes(_jwtSetting.AccessExpiration), signingCredentials: credentials);
token = new JwtSecurityTokenHandler().WriteToken(jwtToken);
return true;
}
}

  d) 添加认证控制器


[Route("api/[controller]")]
[ApiController]
public class AuthenticationController : ControllerBase
{
private IAuthenticateService _authService;
public AuthenticationController(IAuthenticateService authService)
{
_authService = authService;
}
[AllowAnonymous]
[HttpPost, Route("RequestToken")]
public ActionResult RequestToken([FromBody] LoginDto request)
{
if (!ModelState.IsValid)
{
return BadRequest("Invalid Request");
}
string token;
if (_authService.IsAuthenticated(request, out token))
{
return Ok(token);
}
return BadRequest("Invalid Request");
}
}

 6、注入服务:TokenAuthenticationService 、UserService 


services.AddScoped<IUserService, UserService>();
services.AddScoped<IAuthenticateService, TokenAuthenticationService>();

 7、添加测试控制器:


[Authorize]
[Route("api/[controller]")]
[ApiController]
public class AuditLogController : ControllerBase
{
// GET: api/<AuditLogController>
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}

     到此Jwt认证在.net core中已经实现,接下来验证下运行效果


三、验证结果

 1、请求AuditLog接口:api/AuditLog未传入认证信息时:


  


  2、获取Token:


  


 3、添加token调用接口:


  


四、Swagger UI添加认证

  在项目中通常都添加了Swagger UI来展示接口及基础测试,那么如果添加了认证后,如何在调用接口前添加认证信息呢?


  在Startup中:ConfigureServices中添加Swagger设置时,添加认证设置


//注册Swagger生成器,定义一个和多个Swagger 文档
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "AuditLogDemo API", Version = "v1" });
#region 启用swagger验证功能
//添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称一致即可。
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference {
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] { }
}
});
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT授权(数据将在请求头中进行传输) 在下方输入Bearer {token} 即可,注意两者之间有空格",
Name = "Authorization",//jwt默认的参数名称
In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
Type = SecuritySchemeType.ApiKey,
BearerFormat = "JWT",
Scheme = "Bearer",
});
#endregion
});

  运行效果: 添加token->调用需认证接口


   


       


其他:

  源码地址:https://github.com/cwsheng/AuditLogDemo.git


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/cwsheng/p/14289599.html

随机推荐

期货python入门书籍_期货基础书籍有哪些?

一要多学习,多研究。首先要自学,作为小白我认为推荐你看两本书,一本儿书是张龄松的《股票操作学》。这本书大家不要买错有很多仿版或者解读版,记住是台...

weixin_39797780 阅读(167)

20201212go开发环境安装windows版本

20201212go开发环境安装windows版本

GO开发环境安装windows安装包下载安装验证运行goland安装包下载下载链接:https://studygolang.com/dl安装验证cmd输入goversiongoenv则说...

Michael·Sun 阅读(413)

二叉树期权定价python代码_期权的二叉树定价模型

一、套期保值(复制原理)基本思想:构造一个股票和借款的适当组合,使得无论股价如何变动,投资组合的损益都与期权相同,那么创建该投资组合的成本就是期...

weixin_39919089 阅读(999)