ASP.NET Core JWT 认证
本示例是基于GRPC框架下的认证代码与MVC模式稍有区别,直接上代码 服务端代码如下:
public void ConfigureServices(IServiceCollection services)
{
services.AddGrpc();
services.AddSingleton<TicketRepository>();
services.AddAuthorization(options =>
{
options.AddPolicy(JwtBearerDefaults.AuthenticationScheme, policy =>
{
policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
policy.RequireClaim(ClaimTypes.Name);
});
});
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters =
new TokenValidationParameters
{
ValidateAudience = true, //验证受众
ValidateIssuer = true, //验证签发人
ValidateActor = true, //验证签名
ValidateLifetime = true, //是否在令牌生存期间验证
ValidIssuer = "ExampleServer", //令牌发行者
ValidAudience = "ExampleClients", //令牌受众
IssuerSigningKey = SecurityKey, //密钥
};
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<TicketerService>();
endpoints.MapGet("/generateJwtToken", context =>
{
return context.Response.WriteAsync(GenerateJwtToken(context.Request.Query["name"]));
});
});
}
//这里是生成token的代码,当然正常逻辑这里会增加用户密码验证,并做一些权限角色处理
//如正常登录后权限角色写入到redis ,重写 Authorize 特性增加权限验证逻辑
private string GenerateJwtToken(string name)
{
if (string.IsNullOrEmpty(name))
{
throw new InvalidOperationException("Name is not specified.");
}
var claims = new[] { new Claim(ClaimTypes.Name, name) };
var credentials = new SigningCredentials(SecurityKey, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken("ExampleServer", "ExampleClients", claims, expires: DateTime.Now.AddSeconds(60), signingCredentials: credentials);
return JwtTokenHandler.WriteToken(token);
}
客户端调用代码示例:
//登录验证并得到token
private static async Task<string> Authenticate()
{
Console.WriteLine($"Authenticating as {Environment.UserName}...");
var httpClient = new HttpClient();
var request = new HttpRequestMessage
{
RequestUri = new Uri($"{Address}/generateJwtToken?name={HttpUtility.UrlEncode(Environment.UserName)}"),
Method = HttpMethod.Get,
Version = new Version(2, 0)
};
var tokenResponse = await httpClient.SendAsync(request);
tokenResponse.EnsureSuccessStatusCode();
var token = await tokenResponse.Content.ReadAsStringAsync();
Console.WriteLine("Successfully authenticated.");
return token;
}
//调用服务端接口,并加入验证token
private static async Task PurchaseTicket(Ticketer.TicketerClient client, string? token)
{
Console.WriteLine("Purchasing ticket...");
try
{
Metadata? headers = null;
if (token != null)
{
headers = new Metadata();
headers.Add("Authorization", $"Bearer {token}");
headers.Add("alg", "HS256"); //加密方式
}
var response = await client.BuyTicketsAsync(new BuyTicketsRequest { Count = 1 }, headers);
if (response.Success)
{
Console.WriteLine("Purchase successful.");
}
else
{
Console.WriteLine("Purchase failed. No tickets available.");
}
}
catch (Exception ex)
{
Console.WriteLine("Error purchasing ticket." + Environment.NewLine + ex.ToString());
}
}
//服务端代码示例,这里增加 Authorize 特性表示需要验证
//Authorize 的验证规则与验证代理已经在 ConfigureServices 函数配置好。
[Authorize]
public override Task<BuyTicketsResponse> BuyTickets(BuyTicketsRequest request, ServerCallContext context)
{
var user = context.GetHttpContext().User;
return Task.FromResult(new BuyTicketsResponse
{
Success = _ticketRepository.BuyTickets(user.Identity.Name!, request.Count)
});
}
参考:https://www.cnblogs.com/7tiny/archive/2019/06/13/11012035.html
https://cloud.tencent.com/developer/ask/130481
浙公网安备 33010602011771号