我正在开发一个使用appsettings.json文件来跟上某些值的应用程序,包括jwt密钥。然后我使用依赖注入来填充静态类,以便我可以从任何地方访问这些值,包括库。但是,在应用程序运行一段时间后(不完全确定是什么,因为它在30分钟到几个小时之间),该静态类中的值将设置为null,并且应用程序将抛出null异常。我有什么遗漏吗?为什么会这样?代码如下。
public JsonResult GenerateToken([FromBody] LoginModel model)
{
_logger.LogWarning("LoginController-GenerateToken(): The contents of the config file are {0}, {1}, {2}", AuthConfigurations.SecretKey, APIConfigurations.CustomerOneConnectionString, JwtConfigurations.JwtSecretKey);
if (model != null)
{
bool result = LongIn(model); //returns true if login was successful
if (result)
{
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, model.Username),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtConfigurations.JwtSecretKey));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(JwtConfigurations.Issuer, JwtConfigurations.Audience, claims, expires: DateTime.Now.AddSeconds(JwtConfigurations.TokenExpire), signingCredentials: creds);
return Json(new { token = new JwtSecurityTokenHandler().WriteToken(token) });
}
else
{
return Json(null);
}
}
return Json(null);
}
在这里,有时,此调用会抛出异常,因为JwtConfigurations静态属性(Issuer,Audience,JwtSecretKey)为null。我一直在使用记录器来记录这个。
这是静态类和服务类
public class ConfigurationSettings
{
public string Audience { get; set; }
public string Issuer { get; set; }
public int TokenExpire { get; set; }
public string JwtSecretKey { get; set; }
}
public static class JwtConfigurations
{
public static string JwtSecretKey;
public static string Audience;
public static string Issuer;
public static int TokenExpire; //In Seconds
}
和
public class ConfigureHandler : IConfigure
{
private readonly IOptions<ConfigurationSettings> _settings;
public ConfigureHandler(IOptions<ConfigurationSettings> settings, ILogger<ConfigureHandler> logger)
{
_settings = settings;
JwtConfigurations.JwtSecretKey = _settings.Value.JwtSecretKey;
JwtConfigurations.Audience = _settings.Value.Audience;
JwtConfigurations.Issuer = _settings.Value.Issuer;
JwtConfigurations.TokenExpire = _settings.Value.TokenExpire;
}
}
最后,我在启动文件中添加服务。
public void ConfigureServices(IServiceCollection services)
{
.....
services.AddSingleton<IConfigure, ConfigureHandler>();
}
答案 0 :(得分:0)
配置的静态类不应该在2018年使用,它是一个反模式,导致难以测试的类,你永远不知道某个线程是否在执行过程中将其更改为无效。
使用依赖注入/反转控制容器时,应始终将其一直用于应用程序,而不是混合反模式(如静态选项)。
您已经知道如何使用IOptions<T>
为什么不将它注入控制器?!
public class LoginController : Controller
{
private ConfigurationSettings Config { get; }
public LoginController(IOption<ConfigurationSettings> jwtOptions, ... /* other deps */)
{
Config = jwtOptions.Value;
}
public JsonResult GenerateToken([FromBody] LoginModel model)
{
...
// this access the options injected in constructor
var token = new JwtSecurityToken(Config.Issuer, Config.Audience, claims, expires: DateTime.Now.AddSeconds(Config.TokenExpire), signingCredentials: creds);
...
}
}
然后,您可以完全从代码中删除ConfigureHandler
和JwtConfigurations
。
您的案例中的真正问题似乎是,您永远不会解决ConfigureHandler
。只需致电
services.AddSingleton<IConfigure, ConfigureHandler>();
不会创建ConfigureHandler
的实例。它仅在第一次需要时创建。但是这样的方法很危险,因为你永远不知道某些东西会在它之前或之后执行,并且很难跟踪/调试它。只需按照答案前半部分所述使用DI,你就可以了(并且维护或调试的代码较少,难以找到像你现在那样的错误)。