在客户端 API 中使用 JWT 令牌
Posted
技术标签:
【中文标题】在客户端 API 中使用 JWT 令牌【英文标题】:Using JWT Token in Client API 【发布时间】:2021-08-12 04:57:14 【问题描述】:我在 .NET5 中有一个 API,使用 JWTBearer 来保护 API。现在我想配置我的客户端应用程序以使用从 api/gettoken 生成的令牌。它在招摇中工作得很好,但我不知道如何配置我的 MVC 和 API(消费 API)来使用这个令牌。有人可以通过在启动时提供配置服务和配置方法来提供帮助吗
致格伦,
我有 3 个项目 JWT.IDP、JWT.API、JWT.MVC。 JWT.IDP 颁发令牌,我的意图是在 JWT.API 中使用该令牌并从 JWT.MVC 调用 JWT.API 函数。 IDP 运行良好,我可以生成令牌并且我的 JWT.MVC 登录控制器能够接收它。下面代码中的最后一个函数(GetWeatherData)是根据您给出的想法编码的。如果我不通过令牌,我以前会得到 401 错误,现在我得到 500 Internal Server Error
namespace JWT.MVC.Controllers
public class LoginController : Controller
public IActionResult DoLogin()
return View();
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DoLogin([Bind("EmailOrName,Password")] LoginRequestModel loginRequestModel)
var apiName = $"https://localhost:44318/api/User/login";
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.PostAsJsonAsync(apiName, loginRequestModel);
var jasonString = await response.Content.ReadAsStreamAsync();
var data = await JsonSerializer.DeserializeAsync<IEnumerable<AccessibleDb>>
(jasonString, new JsonSerializerOptions() PropertyNameCaseInsensitive = true );
foreach (var item in data)
item.UserName = loginRequestModel.EmailOrName;
return View("SelectDatabase" , data);
public async Task<IActionResult> PostLogin(string db, string user)
TokenRequestModel tokenRequestModel = new TokenRequestModel() Database = db, UserName = user ;
var apiName = $"https://localhost:44318/api/User/tokenonly";
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.PostAsJsonAsync(apiName, tokenRequestModel);
var jasonString = await response.Content.ReadAsStreamAsync();
var data = await JsonSerializer.DeserializeAsync<AuthenticationModel>
(jasonString, new JsonSerializerOptions() PropertyNameCaseInsensitive = true );
var stream = data.Token;
var handler = new JwtSecurityTokenHandler();
var jsonToken = handler.ReadToken(stream);
var tokenS = jsonToken as JwtSecurityToken;
var selectedDb = tokenS.Claims.First(claim => claim.Type == "Database").Value;
ViewBag.SelectedDb = selectedDb;
return View(data);
public async Task<IActionResult> GetWeatherData(string token)
var apiName = $"https://localhost:44338/weatherforecast";
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
HttpResponseMessage response = await httpClient.GetAsync(apiName);
if (!response.IsSuccessStatusCode)
ViewBag.Error = response.StatusCode;
return View("Weatherdata");
var jasonString = await response.Content.ReadAsStreamAsync();
var data = await JsonSerializer.DeserializeAsync<WeatherForecast>
(jasonString, new JsonSerializerOptions() PropertyNameCaseInsensitive = true );
return View("Weatherdata" , data);
JWT.MVC 的启动类如下
public void ConfigureServices(IServiceCollection services)
services.AddControllersWithViews();
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
options.Audience = "SecureApiUser";
options.Authority = "https://localhost:44318";
options.TokenValidationParameters = new TokenValidationParameters
ValidateAudience = false
;
);
JWT.API 的启动类如下
public void ConfigureServices(IServiceCollection services)
services.AddControllers();
//Copy from IS4
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
options.Audience = "SecureApiUser";
options.Authority = "https://localhost:44318";
options.TokenValidationParameters = new TokenValidationParameters
ValidateAudience = false
;
);
//End
services.AddSwaggerGen(c =>
c.SwaggerDoc("v1", new OpenApiInfo Title = "JWT.API", Version = "v1" );
);
JWT.IDP 的启动类如下
public void ConfigureServices(IServiceCollection services)
services.AddControllers();
//Configuration from AppSettings
services.Configure<JwtSettings>(Configuration.GetSection("JWT"));
//User Manager Service
services.AddIdentity<ApplicationUser, IdentityRole>().AddEntityFrameworkStores<IdentityDbContext>();
services.AddScoped<IUserService, UserService>();
//Adding DB Context with MSSQL
services.AddDbContext<IdentityDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("IdentityDbConnectionString"),
b => b.MigrationsAssembly(typeof(IdentityDbContext).Assembly.FullName)));
//Adding Athentication - JWT
services.AddAuthentication(options =>
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
)
.AddJwtBearer(o =>
o.RequireHttpsMetadata = false;
o.SaveToken = false;
o.TokenValidationParameters = new TokenValidationParameters
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes(Convert.ToInt32(Configuration["JWT:DurationInMinutes"])),
ValidIssuer = Configuration["JWT:Issuer"],
ValidAudience = Configuration["JWT:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:Key"]))
;
);
services.AddSwaggerGen(c =>
c.SwaggerDoc("v1", new OpenApiInfo Title = "JWT.IDP", Version = "v1" );
);
JWT 设置如下
"JWT":
"key": "C1CF4B7DC4C4175B6618DE4F55CA4",
"Issuer": "http://localhost:44318",
"Audience": "SecureApiUser",
"DurationInMinutes": 60
,
【问题讨论】:
您好 Jacob,请尝试 Microsoft Docs。这确实是一个非常有用的资源,你应该能够在那里找到你的答案。例如,从阅读Authenticate with bearer tokens 开始。如果您对实施有具体问题,请回来,我们会尽力为您提供帮助! 谢谢丹尼斯。我会尽力让你知道 【参考方案1】:简短的回答是
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", [token])
保持“Bearer”不变,它只是一个常数。将 [token] 替换为您使用的 OAuth 协议返回给我们的 base 64 编码令牌值。
【讨论】:
您好 GlennSills,感谢您提供如此简单的解决方案。我仍在努力解决这个问题。我完成了发布令牌的 API,但如果我有多个客户端使用该令牌。我有以下问题,请您帮忙。 1.我们是否必须在启动时提供任何东西,或者只有您的上述建议就足够了。 2. JWT 的 aud 设置,我们如何传递多个受众 3. 我的客户端 API 或 MVC 如何将自己标识为受众之一 1) 不,把它放在启动中是行不通的。想想看,令牌是短暂的——你得到一个然后你进行身份验证。如果您有很多使用相同令牌的请求,并且您想避免在每个位置对其进行编码,那么我建议编写一个初始化 HttpClient 对象的包装类。然后让所有需要使用 HttpClient 和 at 令牌调用的地方。 2) 当您请求令牌时,您可以请求 1 或多个受众。当服务器创建一个令牌时,它可以用于 1 个或多个受众。 3) 当您在服务器上配置客户端时,您定义了在请求令牌时允许请求的一组受众。 您好格伦,非常感谢您的解释。请把我当作首发。我真的很高兴与您联系。我理解第一点,我会弄清楚如何做到这一点。但关于第 2 点和第 3 点,我需要你的帮助。如果我发布我的代码,您能提供帮助吗?以上是关于在客户端 API 中使用 JWT 令牌的主要内容,如果未能解决你的问题,请参考以下文章
如何从使用 JWT 令牌的 Web 客户端应用程序中注销用户
在 .net core api 中存储/验证存储在 HttpOnly cookie 中的 JWT 令牌