ASP.NET 核心 API 使用 JWT 不记名令牌进行身份验证
ASP.NET Core API authenticate using JWT bearer tokens
我有一个新的 API 我想使用外部安全提供程序(auth 服务器)进行身份验证。我有以下代码,但是在设置了所有内容后调用我的身份验证操作时出现错误。
Startup.cs:
public async void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddScoped<ITemperatureLoggerRepository<ConsolidatedTables>, TemperatureLoggerRepository>();
services.AddDbContext<TemperatureLoggerContext>(options => options.UseSqlServer(Configuration["Data:ConnectionString:TemperatureLoggerDB"]));
services.AddSwaggerGen(swagger =>
{
swagger.SwaggerDoc("v1", new OpenApiInfo { Title = "Temperature Logger API", Version = "Version 1" });
swagger.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
Name = "Authorization",
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: \"Bearer 12345abcdef\"",
});
swagger.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] {}
}
});
});
Response<List<Client>> response = await services.AddAuthServer(Configuration);
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
var signingKeys = new List<SymmetricSecurityKey>();
foreach (var client in response.Data)
{
signingKeys.Add(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(client.Base64Secret)));
}
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = false,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Issuer"],
IssuerSigningKeys = signingKeys
};
}).AddOAuthValidation();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseAuthentication();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Temperature Logger API");
});
}
AuthServer.cs 调用允许访问的客户端列表 API:
public static async Task<Response<List<Client>>> AddAuthServer(this IServiceCollection collection, IConfiguration config)
{
var clientHandler = new HttpClientHandler
{
CookieContainer = new CookieContainer(),
UseCookies = true
};
using (var httpClient = new HttpClient(clientHandler))
{
HttpContent content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "client_credentials"),
new KeyValuePair<string, string>("client_id", config["Jwt:ClientId"]),
new KeyValuePair<string, string>("client_secret", config["Jwt:ClientSecret"])
});
httpClient.BaseAddress = new Uri(config["Jwt:Issuer"]);
var responseMessage = await httpClient.PostAsync(config["Jwt:Issuer"] + "oauth2/token", content);
var result = await responseMessage.Content.ReadAsStringAsync();
_tokenResponse = JsonConvert.DeserializeObject<Token>(result);
}
var clientHandler2 = new HttpClientHandler
{
CookieContainer = new CookieContainer(),
UseCookies = true
};
using (var httpClient2 = new HttpClient(clientHandler2))
{
httpClient2.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _tokenResponse.access_token);
using (var response = await httpClient2.GetAsync(config["Jwt:Issuer"] + "api/Client/GetIdKeys"))
{
if (!response.IsSuccessStatusCode) throw new Exception(response.StatusCode.ToString());
//string clientsResponse = await response.Content.ReadAsStringAsync();
return await response.Content.ReadAsAsync<Response<List<Client>>>();
}
}
}
HomeController.cs(已验证的操作):
[Produces("application/json")]
[Route("api/home")]
[ApiController]
[Authorize]
public class HomeController : ControllerBase
{
[HttpGet]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public IActionResult Index()
{
return Ok("Welcome to our Protected World!");
}
}
结果:
请帮助我如何让它工作。 API 也有分配给它的 ClientId 和 ClientSecret。
我设法找出了问题所在,而且非常简单,但我错过了。它真的与获取我的听众列表或任何额外配置无关。我需要解码我从商店获得的密钥:
var signingKeys = new List<SymmetricSecurityKey>();
foreach (var client in response.Data)
{
signingKeys.Add(new SymmetricSecurityKey(Base64UrlEncoder.DecodeBytes(/***base64Secret***/)));
}
我有一个新的 API 我想使用外部安全提供程序(auth 服务器)进行身份验证。我有以下代码,但是在设置了所有内容后调用我的身份验证操作时出现错误。
Startup.cs:
public async void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddScoped<ITemperatureLoggerRepository<ConsolidatedTables>, TemperatureLoggerRepository>();
services.AddDbContext<TemperatureLoggerContext>(options => options.UseSqlServer(Configuration["Data:ConnectionString:TemperatureLoggerDB"]));
services.AddSwaggerGen(swagger =>
{
swagger.SwaggerDoc("v1", new OpenApiInfo { Title = "Temperature Logger API", Version = "Version 1" });
swagger.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
Name = "Authorization",
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: \"Bearer 12345abcdef\"",
});
swagger.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] {}
}
});
});
Response<List<Client>> response = await services.AddAuthServer(Configuration);
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
var signingKeys = new List<SymmetricSecurityKey>();
foreach (var client in response.Data)
{
signingKeys.Add(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(client.Base64Secret)));
}
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = false,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Issuer"],
IssuerSigningKeys = signingKeys
};
}).AddOAuthValidation();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseAuthentication();
app.UseSwagger();
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Temperature Logger API");
});
}
AuthServer.cs 调用允许访问的客户端列表 API:
public static async Task<Response<List<Client>>> AddAuthServer(this IServiceCollection collection, IConfiguration config)
{
var clientHandler = new HttpClientHandler
{
CookieContainer = new CookieContainer(),
UseCookies = true
};
using (var httpClient = new HttpClient(clientHandler))
{
HttpContent content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "client_credentials"),
new KeyValuePair<string, string>("client_id", config["Jwt:ClientId"]),
new KeyValuePair<string, string>("client_secret", config["Jwt:ClientSecret"])
});
httpClient.BaseAddress = new Uri(config["Jwt:Issuer"]);
var responseMessage = await httpClient.PostAsync(config["Jwt:Issuer"] + "oauth2/token", content);
var result = await responseMessage.Content.ReadAsStringAsync();
_tokenResponse = JsonConvert.DeserializeObject<Token>(result);
}
var clientHandler2 = new HttpClientHandler
{
CookieContainer = new CookieContainer(),
UseCookies = true
};
using (var httpClient2 = new HttpClient(clientHandler2))
{
httpClient2.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _tokenResponse.access_token);
using (var response = await httpClient2.GetAsync(config["Jwt:Issuer"] + "api/Client/GetIdKeys"))
{
if (!response.IsSuccessStatusCode) throw new Exception(response.StatusCode.ToString());
//string clientsResponse = await response.Content.ReadAsStringAsync();
return await response.Content.ReadAsAsync<Response<List<Client>>>();
}
}
}
HomeController.cs(已验证的操作):
[Produces("application/json")]
[Route("api/home")]
[ApiController]
[Authorize]
public class HomeController : ControllerBase
{
[HttpGet]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public IActionResult Index()
{
return Ok("Welcome to our Protected World!");
}
}
结果:
请帮助我如何让它工作。 API 也有分配给它的 ClientId 和 ClientSecret。
我设法找出了问题所在,而且非常简单,但我错过了。它真的与获取我的听众列表或任何额外配置无关。我需要解码我从商店获得的密钥:
var signingKeys = new List<SymmetricSecurityKey>();
foreach (var client in response.Data)
{
signingKeys.Add(new SymmetricSecurityKey(Base64UrlEncoder.DecodeBytes(/***base64Secret***/)));
}