.Net gRPC使用Jwt验证详细教程
继上一篇文章 玩转.Net gRPC简单使用详细教程
首先在服务端 定义获取身份验证Token方法,在Message.proto文件
message TokenRequest{
string username = 1;
string password = 2;
}
message TokenResponse{
string token = 1;
google.protobuf.Timestamp expiration = 2;
bool success = 3;
}
service EmployeeService{
rpc GetByNo(GetByNoRequest) returns (EmployeeResponse);
rpc GetAll(GetAllRequest) returns (stream EmployeeResponse);
rpc AddPhoto(stream AddPhotoRequest) returns (AddPhotoResponse);
rpc Save(EmployeeRequest) returns (EmployeeResponse);
rpc SaveAll(stream EmployeeRequest) returns (stream EmployeeResponse);
rpc CreateToken(TokenRequest) returns (TokenResponse);
}
安装Nuget包 Microsoft.AspNetCore.Authentication.JwtBearer
StartUp.cs中:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<JwtTokenValidationService>();
services.AddGrpc();
services.AddAuthorization();
services.AddAuthentication()
.AddJwtBearer(options=> {
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,//是否验证Issuer
ValidateAudience = true,//是否验证Audience
ValidateLifetime = true,//是否验证失效时间
ClockSkew = TimeSpan.FromSeconds(30),
ValidateIssuerSigningKey = true,//是否验证SecurityKey
ValidIssuer = "localhost",
ValidAudience = "localhost",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("wef1561fwffwef5q1wd51z117wqd05f8ewgt515qwd"))
};
});
}
app.UseRouting();
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<MyEmployeeService>();
});
接着创建服务 JwtTokenValidationService.cs
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
namespace GrpcServer.Web.Services
{
public class TokenModel
{
public string Token { get; set; }
public DateTime Expiration { get; set; }
public bool Sucess { get; set; }
}
public class UserModel
{
public string UserName { get; set; }
public string PassWord { get; set; }
}
public class JwtTokenValidationService
{
public async Task<TokenModel> GenerateTokenAsync(UserModel model)
{
if (model.UserName == "admin" && model.PassWord == "123456")
{
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub,"email@126.com"),
new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.UniqueName,"admin")
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("wef1561fwffwef5q1wd51z117wqd05f8ewgt515qwd"));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
"localhost",// Issuer 颁发者,通常为STS服务器地址
"localhost",// Audience Token的作用对象,也就是被访问的资源服务器授权标识
claims,
DateTime.Now, //Token生效时间,在此之前不可用
DateTime.Now.AddMinutes(30), //Token过期时间,在此之后不可用
creds);
return new TokenModel
{
Token = new JwtSecurityTokenHandler().WriteToken(token),
Expiration = token.ValidTo,
Sucess = true
};
}
return new TokenModel
{
Sucess = false
};
}
}
}
在MyEmployeeService.cs中实现验证方法:
[Authorize(AuthenticationSchemes =JwtBearerDefaults.AuthenticationScheme)]
public class MyEmployeeService : EmployeeServiceBase{
private readonly ILogger<MyEmployeeService> logger;
private readonly JwtTokenValidationService jwtTokenValidationService;
public MyEmployeeService(ILogger<MyEmployeeService> logger,
JwtTokenValidationService jwtTokenValidationService)
{
this.logger = logger;
this.jwtTokenValidationService = jwtTokenValidationService;
}
[AllowAnonymous]
public override async Task<TokenResponse> CreateToken(TokenRequest request, ServerCallContext context)
{
var userModel = new UserModel
{
UserName = request.Username,
PassWord = request.Password
};
var response = await jwtTokenValidationService.GenerateTokenAsync(userModel);
if (response.Sucess)
{
return new TokenResponse
{
Token = response.Token,
Expiration = Timestamp.FromDateTime(response.Expiration),
Success = true
};
}
return new TokenResponse
{
Success = false
};
}
}
服务端就写完了,先运行起来。
接下来是客户端:
定义两个变量
private static string _token;
private static DateTime _expiration = DateTime.MinValue;
实现验证方法如下:
private static bool NeedToken() => string.IsNullOrEmpty(_token) || _expiration > DateTime.UtcNow;
public static async Task GetByNoAsync(EmployeeService.EmployeeServiceClient client)
{
if (!NeedToken()|| await GetTokenAsync(client))
{
var headers = new Metadata
{
{"Authorization",$"Bearer {_token}" }
};
var response = await client.GetByNoAsync(new GetByNoRequest()
{
No = 1994
}, headers);
Console.WriteLine(response);
}
}
private static async Task<bool> GetTokenAsync(EmployeeService.EmployeeServiceClient client)
{
var request = new TokenRequest
{
Username = "admin", Password = "123456"
};
var response = await client.CreateTokenAsync(request);
if (response.Success)
{
_token = response.Token;
_expiration = response.Expiration.ToDateTime();
return true;
}
return false;
}
接着运行dotnet run 1