在 ASP.NET 核心 MVC 中传递 API 键的最佳实践
Best practices for passing in API key in ASP.NET Core MVC
我正在使用 MVC 在 ASP.NET 核心中开发一个简单的天气仪表板。我已经弄清楚如何将天气 API 调用的 URI 基地址从 appsettings 传递到配置设置,然后传递到调用天气 API:
的界面
应用程序设置:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
//Here:
"openWeatherAPI": "https://api.openweathermap.org/",
}
启动配置:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
//Here
string uri = Configuration.GetValue<string>("openWeatherAPI");
services.AddControllersWithViews();
services.AddHttpClient<IForecastRepository, ForecastRepository>(c =>
{
//And Here:
c.BaseAddress = new Uri(uri);
}
);
预测界面:
public interface IForecastRepository
{
Task<CityModel> GetMovieDetailsAsync(string cityName);
}
public class ForecastRepository : IForecastRepository
{
private readonly HttpClient _httpClient;
public ForecastRepository(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<CityModel> GetMovieDetailsAsync(string cityName)
{
string IDOWeather = "/*my api key is hardcoded in here*/";
var queryString = $"data/2.5/weather?q={cityName}&units=imperial&APPID={IDOWeather}";
var response = await _httpClient.GetStringAsync(queryString);
//...code conitnues
有没有类似的方法可以传入 API 键?据我了解,将其写入我所在的应用程序并不是最佳做法。
关于 HttpClientFactory 的讨论:
天气控制器:
public class WeatherController : Controller
{
private readonly IForecastRepository _forecastRepository;
public WeatherController(IForecastRepository forecastRepository)
{
_forecastRepository = forecastRepository;
}
public IActionResult SearchCity()
{
var viewModel = new CityModel();
return View(viewModel);
}
public IActionResult City()
{
var viewModel = new CityModel();
return View(viewModel);
}
[HttpPost]
public async Task<IActionResult> SearchResults(CityModel titleFromView)
{
var movieDetail = await _forecastRepository.GetMovieDetailsAsync(titleFromView.Name);
return View("City", movieDetail);
试试这个代码
public class ForecastRepository : IForecastRepository
{
private readonly HttpClient _httpClient;
private readonly string _apiKey;
public ForecastRepository(HttpClient httpClient, IConfiguration configuration)
{
_httpClient = httpClient;
_apiKey = configuration.GetValue<string>("idoWeather");
//or
_apiKey = configuration["idoWeather"];
}
public async Task<CityModel> GetMovieDetailsAsync(string cityName)
{
string IDOWeather = _apiKey;
var queryString = $"data/2.5/weather?q={cityName}&units=imperial&APPID={IDOWeather}";
var response = await _httpClient.GetStringAsync(queryString);
//...code conitnues
}
应用程序设置:
{
....
"idoWeather": "apikey",
"openWeatherAPI": "https://api.openweathermap.org/",
}
顺便说一句,我强烈建议您使用 HttpClientFactory。如果您需要具有不同 url 的 httpClient,则必须以某种方式更改 baseUrl。您可以在启动时创建一组类型化或命名的 http 客户端,但由于您通常不需要所有这些客户端,因此最好在需要时创建。
有关更多信息,您可以阅读我的另一个答案
private readonly IHttpClientFactory _clientFactory
private readonly IConfiguration _configuration;
public ForecastRepository(IHttpClientFactory clientFactory, IConfiguration configuration)
{
_configuration=configuration;
_clientFactory = clientFactory;
}
public async Task<CityModel> GetMovieDetailsAsync(string cityName)
{
var baseAddress = _configuration.GetValue<string>("openWeatherAPI");
var IDOWeather = _configuration.GetValue<string>("idoWeather");
//or
var baseAddress = _configuration["openWeatherAPI"];
var IDOWeather = _configuration["idoWeather"];
var queryString = $"data/2.5/weather?q={cityName}&units=imperial&APPID={IDOWeather}";
var httpClient = _clientFactory.CreateClient();
httpClient.BaseAddress = new Uri(baseAddress);
var response = await httpClient.GetStringAsync(queryString);
使用工厂替换
services.AddHttpClient<IForecastRepository, ForecastRepository>(c =>
{
//And Here:
c.BaseAddress = new Uri(uri);
}
);
和
services.AddHttpClient();
并且由于您使用的是存储库,因此必须将其添加到 DI 服务中
services.AddScoped<IForecastRepository , ForecastRepository>();
我正在使用 MVC 在 ASP.NET 核心中开发一个简单的天气仪表板。我已经弄清楚如何将天气 API 调用的 URI 基地址从 appsettings 传递到配置设置,然后传递到调用天气 API:
的界面应用程序设置:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
//Here:
"openWeatherAPI": "https://api.openweathermap.org/",
}
启动配置:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
//Here
string uri = Configuration.GetValue<string>("openWeatherAPI");
services.AddControllersWithViews();
services.AddHttpClient<IForecastRepository, ForecastRepository>(c =>
{
//And Here:
c.BaseAddress = new Uri(uri);
}
);
预测界面:
public interface IForecastRepository
{
Task<CityModel> GetMovieDetailsAsync(string cityName);
}
public class ForecastRepository : IForecastRepository
{
private readonly HttpClient _httpClient;
public ForecastRepository(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<CityModel> GetMovieDetailsAsync(string cityName)
{
string IDOWeather = "/*my api key is hardcoded in here*/";
var queryString = $"data/2.5/weather?q={cityName}&units=imperial&APPID={IDOWeather}";
var response = await _httpClient.GetStringAsync(queryString);
//...code conitnues
有没有类似的方法可以传入 API 键?据我了解,将其写入我所在的应用程序并不是最佳做法。
关于 HttpClientFactory 的讨论:
天气控制器:
public class WeatherController : Controller
{
private readonly IForecastRepository _forecastRepository;
public WeatherController(IForecastRepository forecastRepository)
{
_forecastRepository = forecastRepository;
}
public IActionResult SearchCity()
{
var viewModel = new CityModel();
return View(viewModel);
}
public IActionResult City()
{
var viewModel = new CityModel();
return View(viewModel);
}
[HttpPost]
public async Task<IActionResult> SearchResults(CityModel titleFromView)
{
var movieDetail = await _forecastRepository.GetMovieDetailsAsync(titleFromView.Name);
return View("City", movieDetail);
试试这个代码
public class ForecastRepository : IForecastRepository
{
private readonly HttpClient _httpClient;
private readonly string _apiKey;
public ForecastRepository(HttpClient httpClient, IConfiguration configuration)
{
_httpClient = httpClient;
_apiKey = configuration.GetValue<string>("idoWeather");
//or
_apiKey = configuration["idoWeather"];
}
public async Task<CityModel> GetMovieDetailsAsync(string cityName)
{
string IDOWeather = _apiKey;
var queryString = $"data/2.5/weather?q={cityName}&units=imperial&APPID={IDOWeather}";
var response = await _httpClient.GetStringAsync(queryString);
//...code conitnues
}
应用程序设置:
{
....
"idoWeather": "apikey",
"openWeatherAPI": "https://api.openweathermap.org/",
}
顺便说一句,我强烈建议您使用 HttpClientFactory。如果您需要具有不同 url 的 httpClient,则必须以某种方式更改 baseUrl。您可以在启动时创建一组类型化或命名的 http 客户端,但由于您通常不需要所有这些客户端,因此最好在需要时创建。
有关更多信息,您可以阅读我的另一个答案
private readonly IHttpClientFactory _clientFactory
private readonly IConfiguration _configuration;
public ForecastRepository(IHttpClientFactory clientFactory, IConfiguration configuration)
{
_configuration=configuration;
_clientFactory = clientFactory;
}
public async Task<CityModel> GetMovieDetailsAsync(string cityName)
{
var baseAddress = _configuration.GetValue<string>("openWeatherAPI");
var IDOWeather = _configuration.GetValue<string>("idoWeather");
//or
var baseAddress = _configuration["openWeatherAPI"];
var IDOWeather = _configuration["idoWeather"];
var queryString = $"data/2.5/weather?q={cityName}&units=imperial&APPID={IDOWeather}";
var httpClient = _clientFactory.CreateClient();
httpClient.BaseAddress = new Uri(baseAddress);
var response = await httpClient.GetStringAsync(queryString);
使用工厂替换
services.AddHttpClient<IForecastRepository, ForecastRepository>(c =>
{
//And Here:
c.BaseAddress = new Uri(uri);
}
);
和
services.AddHttpClient();
并且由于您使用的是存储库,因此必须将其添加到 DI 服务中
services.AddScoped<IForecastRepository , ForecastRepository>();