前言
上一节主要是从后端(服务端)的角度,介绍了注册信息、身份验证、创建Token、验证Token、授权等安全措施的主要流程。
这节介绍从MVC前端访问服务端的角度,来介绍如何获取Token、使用Token。
一、添加类
添加相关类和配置信息。
凭证类
public class AppCredential
{
public string ClientId { get; set; } = string.Empty;
public string Secret { get; set; } = string.Empty;
}
JWTToken类
public class JwtToken
{
[JsonProperty("access_token")]
public string? AccessToken { get; set; }
[JsonProperty("expires_at")]
public DateTime ExpiresAt { get; set; }
}
appsettings.json文件中配置ClientId和Secret信息
二、添加JWT
1. 添加JWT到Header
在WebApiExecuter中添加方法,认证->获取JWT->Header中添加JWT
new AuthenticationHeaderValue(“Bearer”, token?.AccessToken)方法中会有Bearer字符,在服务端获取时特殊处理掉
private async Task AddJwtToHeader(HttpClient httpClient)
{
var clientId = configuration.GetValue<string>("ClientId");
var secret = configuration.GetValue<string>("Secret");
// Authenticate
var authoClient = httpClientFactory.CreateClient(authApiName);
var response = await authoClient.PostAsJsonAsync("auth", new AppCredential()
{
ClientId = clientId,
Secret = secret
});
response.EnsureSuccessStatusCode();
// Get the JWT
string strToken = await response.Content.ReadAsStringAsync();
var token = JsonConvert.DeserializeObject<JwtToken>(strToken);
// Pass the JWT to endpoints through the http headers
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token?.AccessToken);
}
2. 使用JWT
在http请求方法前都添加该方法
三、存储和再用JWT
当前是每次访问都生成新的JWT,可以将JWT保存到session里,如果没有过期,就直接使用。
3.1 添加session服务
在program.cs里添加Session和IHttpContextAccessor
3.2 存储和获取JWT
获取IHttpContextAccessor
private readonly IHttpContextAccessor httpContextAccessor;
public WebApiExecuter(IHttpClientFactory httpClientFactory, IConfiguration configuration, IHttpContextAccessor httpContextAccessor)
{
this.httpClientFactory = httpClientFactory;
this.configuration = configuration;
this.httpContextAccessor = httpContextAccessor;
}
从类里的IHttpContextAccessor存储和获取token字符
private async Task AddJwtToHeader(HttpClient httpClient)
{
JwtToken? token = null;
string? strToken = httpContextAccessor.HttpContext?.Session.GetString("access_token");
if (!string.IsNullOrWhiteSpace(strToken))
{
token = JsonConvert.DeserializeObject<JwtToken>(strToken);
}
if (token == null || token.ExpiresAt <= DateTime.UtcNow)
{
var clientId = configuration.GetValue<string>("ClientId");
var secret = configuration.GetValue<string>("Secret");
// Authenticate
var authoClient = httpClientFactory.CreateClient(authApiName);
var response = await authoClient.PostAsJsonAsync("auth", new AppCredential()
{
ClientId = clientId,
Secret = secret
});
response.EnsureSuccessStatusCode();
// Get the JWT
strToken = await response.Content.ReadAsStringAsync();
token = JsonConvert.DeserializeObject<JwtToken>(strToken);
httpContextAccessor.HttpContext?.Session.SetString("access_token", strToken);
}
// Pass the JWT to endpoints through the http headers
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token?.AccessToken);
}