Asp.net core 3.1 如何从Startup.CS查询数据库

Asp.net core 3.1 如何从Startup.CS查询数据库,asp.net-core-3.1,Asp.net Core 3.1,我正在startup.cs中进行用户身份验证。我需要使用OpenIDConnect索赔信息查询我的数据库。这就是我所做的,但不知道如何让连接工作。我尝试在startup.cs顶部注入db查询构造函数,如下所示,然后调用查询: public class Startup { protected IAdoSqlService _adoSqlService; public Startup(IConfiguration configuration, IAdoSqlServi

我正在startup.cs中进行用户身份验证。我需要使用OpenIDConnect索赔信息查询我的数据库。这就是我所做的,但不知道如何让连接工作。我尝试在startup.cs顶部注入db查询构造函数,如下所示,然后调用查询:

public class Startup
{        
    protected IAdoSqlService _adoSqlService;
    public Startup(IConfiguration configuration, IAdoSqlService adoSqlService)
    {
        Configuration = configuration;
         _adoSqlService = adoSqlService;
    }
    
    public void ConfigureServices(IServiceCollection services)
    {
        // do ConfigureServices stuff
        
        options.Events = new OpenIdConnectEvents()
        {
            OnTokenValidated = async ctx =>
            {
                // This is the ClaimsIdentity created by OpenID Connect, you can add claims to it directly

                ClaimsIdentity claimsIdentity = ctx.Principal.Identities.FirstOrDefault();
                string userntid = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "preferred_username").Value;

                //How do I call the database to run the following query 
                int isUser = _adoSqlService.isUser(userntid);

                if (isUser > 0)
                {
                     claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "user"));
                }
                else
                {
                    claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "not authorized"));
                }
            }
        }
        
        //More stuff
    }
}
当我运行上述程序时,它会在program.cs中出错,甚至在运行之前会出现以下错误
System.InvalidOperationException:'在尝试激活'XXXX.Startup'时,无法解析类型'XXXX.Services.IAdoSqlService'的服务。'

那么我如何调用adoSqlService.isUser(userntid)到数据库

我没有使用EF

解决方案

我通过以下步骤解决了这个问题:

  • 在执行身份验证之前,我将大部分服务移至
    ConfigureServices
    部分的顶部(基于@qudus所说的内容)

  • 我从
    startup.cs
    的顶部删除了数据库注入代码

  • 最后,我将
    OnTokenValidated
    更改为使用以下内容:

    ctx.HttpContext.RequestServices.GetRequiredService()

  • 代码如下:

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        internal static IConfiguration Configuration { get; private set; }
    
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            var connectionSection = Configuration.GetSection("ConnectionStrings");
            services.Configure<ConnectionStrings>(connectionSection);
            services.AddScoped<IAdoSqlService, AdoSqlService>();
            services.AddControllersWithViews();
            services.AddHttpContextAccessor();            
            services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services.AddSession();
    
            // Load the Federation configuration section from app settings
            var federationConfig = Configuration.GetSection("Federation");
            services.Configure<CookiePolicyOptions>(options =>
            {
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.AddAuthentication(sharedOptions =>
            {
                sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            })
            .AddCookie(options =>
            {
                options.ExpireTimeSpan = TimeSpan.FromHours(2);//default is 14days
                options.SlidingExpiration = true;// default
                options.AccessDeniedPath = "/Error/AuthenticateError";// set a custom error access denied error page. this would need to be created/handled in your app.
            })
            .AddOpenIdConnect(options =>
            {
                //Set Options here......
    
                //optional customizations to the auth and failure events
                options.Events = new OpenIdConnectEvents()
                {
                    OnRedirectToIdentityProvider = context =>
                    {
                        return Task.CompletedTask;
                    },
                    OnRemoteFailure = context =>
                    {
                        // handle an error response from Federation and redirect the user to a custom error page instead
                        context.Response.Redirect("/Error/401");
                        context.HandleResponse();
                        return Task.CompletedTask;
                    },
                    OnTokenValidated = async ctx =>
                    {
                        // This is the ClaimsIdentity created by OpenID Connect, you can add claims to it directly
                        ClaimsIdentity claimsIdentity = ctx.Principal.Identities.FirstOrDefault();
                        string userntid = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "preferred_username").Value;
                        string username = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "name").Value;
    
                        int isUser = 0;
                        int isAdmin = 0;
    
                        try 
                        { 
                            var db = ctx.HttpContext.RequestServices.GetRequiredService<IAdoSqlService>();
                            isUser = db.isUser(userntid);
                            isAdmin = db.isAdmin(userntid);
                        }
                        catch (Exception ex)
                        {
                            string error = ex.Message;
                        }
    
                        AppHttpContext.Current.Session.SetString("IsUser", "false");
                        if (isUser > 0)
                        {
                            claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "user"));
                            AppHttpContext.Current.Session.SetString("IsUser", "true");
                        }
    
                        AppHttpContext.Current.Session.SetString("IsUserAdmin", "false");
                        if (isAdmin > 0)
                        {
                            claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "admin"));
                            AppHttpContext.Current.Session.SetString("IsUserAdmin", "true");
                        }
    
                        if (isUser == 0 && isAdmin == 0)
                        {
                            claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "not authorized"));
                        }
    
                    }
                };
            });
    
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        internal static IConfiguration Configuration { get; private set; }
    
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            var connectionSection = Configuration.GetSection("ConnectionStrings");
            services.Configure<ConnectionStrings>(connectionSection);
            services.AddScoped<IAdoSqlService, AdoSqlService>();
            services.AddControllersWithViews();
            services.AddHttpContextAccessor();            
            services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services.AddSession();
    
            // Load the Federation configuration section from app settings
            var federationConfig = Configuration.GetSection("Federation");
            services.Configure<CookiePolicyOptions>(options =>
            {
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.AddAuthentication(sharedOptions =>
            {
                sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            })
            .AddCookie(options =>
            {
                options.ExpireTimeSpan = TimeSpan.FromHours(2);//default is 14days
                options.SlidingExpiration = true;// default
                options.AccessDeniedPath = "/Error/AuthenticateError";// set a custom error access denied error page. this would need to be created/handled in your app.
            })
            .AddOpenIdConnect(options =>
            {
                //Set Options here......
    
                //optional customizations to the auth and failure events
                options.Events = new OpenIdConnectEvents()
                {
                    OnRedirectToIdentityProvider = context =>
                    {
                        return Task.CompletedTask;
                    },
                    OnRemoteFailure = context =>
                    {
                        // handle an error response from Federation and redirect the user to a custom error page instead
                        context.Response.Redirect("/Error/401");
                        context.HandleResponse();
                        return Task.CompletedTask;
                    },
                    OnTokenValidated = async ctx =>
                    {
                        // This is the ClaimsIdentity created by OpenID Connect, you can add claims to it directly
                        ClaimsIdentity claimsIdentity = ctx.Principal.Identities.FirstOrDefault();
                        string userntid = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "preferred_username").Value;
                        string username = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "name").Value;
    
                        int isUser = 0;
                        int isAdmin = 0;
    
                        try 
                        { 
                            var db = ctx.HttpContext.RequestServices.GetRequiredService<IAdoSqlService>();
                            isUser = db.isUser(userntid);
                            isAdmin = db.isAdmin(userntid);
                        }
                        catch (Exception ex)
                        {
                            string error = ex.Message;
                        }
    
                        AppHttpContext.Current.Session.SetString("IsUser", "false");
                        if (isUser > 0)
                        {
                            claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "user"));
                            AppHttpContext.Current.Session.SetString("IsUser", "true");
                        }
    
                        AppHttpContext.Current.Session.SetString("IsUserAdmin", "false");
                        if (isAdmin > 0)
                        {
                            claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "admin"));
                            AppHttpContext.Current.Session.SetString("IsUserAdmin", "true");
                        }
    
                        if (isUser == 0 && isAdmin == 0)
                        {
                            claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "not authorized"));
                        }
    
                    }
                };
            });
    
    公共类启动
    {
    公共启动(IConfiguration配置)
    {
    配置=配置;
    }
    内部静态IConfiguration配置{get;private set;}
    //此方法由运行时调用。请使用此方法将服务添加到容器中。
    public void配置服务(IServiceCollection服务)
    {
    var connectionSection=Configuration.GetSection(“connectionString”);
    服务。配置(连接部分);
    services.addScope();
    services.AddControllersWithViews();
    AddHttpContextAccessor();
    services.AddSingleton();
    services.AddSingleton();
    services.AddSession();
    //从应用程序设置加载联合配置部分
    var federationConfig=Configuration.GetSection(“联合”);
    配置(选项=>
    {
    options.MinimumSameSitePolicy=SameSiteMode.None;
    });
    services.AddAuthentication(sharedOptions=>
    {
    sharedOptions.DefaultScheme=CookieAuthenticationDefaults.AuthenticationScheme;
    sharedOptions.DefaultChallengeScheme=OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddCookie(选项=>
    {
    options.ExpireTimeSpan=TimeSpan.FromHours(2);//默认值为14天
    options.SlidingExpiration=true;//默认值
    options.AccessDeniedPath=“/Error/AuthenticateError”;//设置自定义错误访问拒绝错误页。这需要在应用程序中创建/处理。
    })
    .AddOpenIdConnect(选项=>
    {
    //在这里设置选项。。。。。。
    //对身份验证和失败事件的可选自定义
    options.Events=new OpenIdConnectEvents()
    {
    OnRedirectToIdentityProvider=上下文=>
    {
    返回Task.CompletedTask;
    },
    OnRemoteFailure=上下文=>
    {
    //处理来自联合的错误响应,并将用户重定向到自定义错误页
    context.Response.Redirect(“/Error/401”);
    context.HandleResponse();
    返回Task.CompletedTask;
    },
    OnTokenValidated=异步ctx=>
    {
    //这是OpenID Connect创建的索赔实体,您可以直接向其添加索赔
    ClaimsIdentity ClaimsIdentity=ctx.Principal.identies.FirstOrDefault();
    字符串userntid=claimsIdentity.Claims.FirstOrDefault(c=>c.Type==“首选用户名”).Value;
    字符串username=claimsIdentity.Claims.FirstOrDefault(c=>c.Type==“name”).Value;
    int isUser=0;
    int-isAdmin=0;
    尝试
    { 
    var db=ctx.HttpContext.RequestServices.GetRequiredService();
    isUser=db.isUser(userntid);
    isAdmin=db.isAdmin(userntid);
    }
    捕获(例外情况除外)
    {
    字符串错误=例如消息;
    }
    AppHttpContext.Current.Session.SetString(“IsUser”,“false”);
    如果(isUser>0)
    {
    claimsIdentity.AddClaim(新索赔(ClaimTypes.Role,“用户”);
    AppHttpContext.Current.Session.SetString(“IsUser”,“true”);
    }
    AppHttpContext.Current.Session.SetString(“IsUserAdmin”、“false”);
    如果(isAdmin>0)
    {
    claimsIdentity.AddClaim(新的Claim(ClaimTypes.Role,“admin”);
    AppHttpContext.Current.Session.SetString(“IsUserAdmin”、“true”);
    }
    if(isUser==0&&isAdmin==0)
    {
    claimsIdentity.AddClaim(新索赔(ClaimTypes.Role,“未授权”);
    }
    }
    };
    });
    
    解决方案

    我通过以下步骤解决了这个问题:

  • 在执行身份验证之前,我将大部分服务移至
    ConfigureServices
    部分的顶部(基于@qudus所说的内容)

  • 我从startup.cs的顶部删除了数据库注入代码

  • 最后,我将
    OnTokenValidated
    更改为使用以下内容:

    ctx.HttpContext.RequestServices.GetRequiredService()

  • 代码如下:

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        internal static IConfiguration Configuration { get; private set; }
    
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            var connectionSection = Configuration.GetSection("ConnectionStrings");
            services.Configure<ConnectionStrings>(connectionSection);
            services.AddScoped<IAdoSqlService, AdoSqlService>();
            services.AddControllersWithViews();
            services.AddHttpContextAccessor();            
            services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services.AddSession();
    
            // Load the Federation configuration section from app settings
            var federationConfig = Configuration.GetSection("Federation");
            services.Configure<CookiePolicyOptions>(options =>
            {
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.AddAuthentication(sharedOptions =>
            {
                sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            })
            .AddCookie(options =>
            {
                options.ExpireTimeSpan = TimeSpan.FromHours(2);//default is 14days
                options.SlidingExpiration = true;// default
                options.AccessDeniedPath = "/Error/AuthenticateError";// set a custom error access denied error page. this would need to be created/handled in your app.
            })
            .AddOpenIdConnect(options =>
            {
                //Set Options here......
    
                //optional customizations to the auth and failure events
                options.Events = new OpenIdConnectEvents()
                {
                    OnRedirectToIdentityProvider = context =>
                    {
                        return Task.CompletedTask;
                    },
                    OnRemoteFailure = context =>
                    {
                        // handle an error response from Federation and redirect the user to a custom error page instead
                        context.Response.Redirect("/Error/401");
                        context.HandleResponse();
                        return Task.CompletedTask;
                    },
                    OnTokenValidated = async ctx =>
                    {
                        // This is the ClaimsIdentity created by OpenID Connect, you can add claims to it directly
                        ClaimsIdentity claimsIdentity = ctx.Principal.Identities.FirstOrDefault();
                        string userntid = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "preferred_username").Value;
                        string username = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "name").Value;
    
                        int isUser = 0;
                        int isAdmin = 0;
    
                        try 
                        { 
                            var db = ctx.HttpContext.RequestServices.GetRequiredService<IAdoSqlService>();
                            isUser = db.isUser(userntid);
                            isAdmin = db.isAdmin(userntid);
                        }
                        catch (Exception ex)
                        {
                            string error = ex.Message;
                        }
    
                        AppHttpContext.Current.Session.SetString("IsUser", "false");
                        if (isUser > 0)
                        {
                            claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "user"));
                            AppHttpContext.Current.Session.SetString("IsUser", "true");
                        }
    
                        AppHttpContext.Current.Session.SetString("IsUserAdmin", "false");
                        if (isAdmin > 0)
                        {
                            claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "admin"));
                            AppHttpContext.Current.Session.SetString("IsUserAdmin", "true");
                        }
    
                        if (isUser == 0 && isAdmin == 0)
                        {
                            claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "not authorized"));
                        }
    
                    }
                };
            });
    
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        internal static IConfiguration Configuration { get; private set; }
    
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            var connectionSection = Configuration.GetSection("ConnectionStrings");
            services.Configure<ConnectionStrings>(connectionSection);
            services.AddScoped<IAdoSqlService, AdoSqlService>();
            services.AddControllersWithViews();
            services.AddHttpContextAccessor();            
            services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services.AddSession();
    
            // Load the Federation configuration section from app settings
            var federationConfig = Configuration.GetSection("Federation");
            services.Configure<CookiePolicyOptions>(options =>
            {
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.AddAuthentication(sharedOptions =>
            {
                sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            })
            .AddCookie(options =>
            {
                options.ExpireTimeSpan = TimeSpan.FromHours(2);//default is 14days
                options.SlidingExpiration = true;// default
                options.AccessDeniedPath = "/Error/AuthenticateError";// set a custom error access denied error page. this would need to be created/handled in your app.
            })
            .AddOpenIdConnect(options =>
            {
                //Set Options here......
    
                //optional customizations to the auth and failure events
                options.Events = new OpenIdConnectEvents()
                {
                    OnRedirectToIdentityProvider = context =>
                    {
                        return Task.CompletedTask;
                    },
                    OnRemoteFailure = context =>
                    {
                        // handle an error response from Federation and redirect the user to a custom error page instead
                        context.Response.Redirect("/Error/401");
                        context.HandleResponse();
                        return Task.CompletedTask;
                    },
                    OnTokenValidated = async ctx =>
                    {
                        // This is the ClaimsIdentity created by OpenID Connect, you can add claims to it directly
                        ClaimsIdentity claimsIdentity = ctx.Principal.Identities.FirstOrDefault();
                        string userntid = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "preferred_username").Value;
                        string username = claimsIdentity.Claims.FirstOrDefault(c => c.Type == "name").Value;
    
                        int isUser = 0;
                        int isAdmin = 0;
    
                        try 
                        { 
                            var db = ctx.HttpContext.RequestServices.GetRequiredService<IAdoSqlService>();
                            isUser = db.isUser(userntid);
                            isAdmin = db.isAdmin(userntid);
                        }
                        catch (Exception ex)
                        {
                            string error = ex.Message;
                        }
    
                        AppHttpContext.Current.Session.SetString("IsUser", "false");
                        if (isUser > 0)
                        {
                            claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "user"));
                            AppHttpContext.Current.Session.SetString("IsUser", "true");
                        }
    
                        AppHttpContext.Current.Session.SetString("IsUserAdmin", "false");
                        if (isAdmin > 0)
                        {
                            claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "admin"));
                            AppHttpContext.Current.Session.SetString("IsUserAdmin", "true");
                        }
    
                        if (isUser == 0 && isAdmin == 0)
                        {
                            claimsIdentity.AddClaim(new Claim(ClaimTypes.Role, "not authorized"));
                        }
    
                    }
                };
            });
    
    公共类启动
    {
    公共启动