静态对象随机变为空

时间:2018-01-11 15:19:39

标签: c# .net asp.net-core scope nullpointerexception

我正在开发一个使用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>();
}

1 个答案:

答案 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);
        ...
    }
}

然后,您可以完全从代码中删除ConfigureHandlerJwtConfigurations

您的案例中的真正问题似乎是,您永远不会解决ConfigureHandler。只需致电

services.AddSingleton<IConfigure, ConfigureHandler>();

不会创建ConfigureHandler的实例。它仅在第一次需要时创建。但是这样的方法很危险,因为你永远不知道某些东西会在它之前或之后执行,并且很难跟踪/调试它。只需按照答案前半部分所述使用DI,你就可以了(并且维护或调试的代码较少,难以找到像你现在那样的错误)。