如何在 .Net Core MVC 中实现 IAuthorization Filter 时获取连接字符串?

Posted

技术标签:

【中文标题】如何在 .Net Core MVC 中实现 IAuthorization Filter 时获取连接字符串?【英文标题】:How to get connectionstring in implementing IAuthorization Filter in .Net Core MVC? 【发布时间】:2021-11-16 13:17:33 【问题描述】:

我是 .Net Core 的新手,我想调用我的数据库以从数据库中获取用户的所有权限。因此,在实现 IAuthorization Filter 时,我无法获取连接字符串。

授权属性:

using Demo.Respositories;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;

namespace Demo.Web.Providers

 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomAuthorizeAttribute : Attribute, IAuthorizationFilter

    public void OnAuthorization(AuthorizationFilterContext context)
    
        try
        
            if (context.HttpContext.User.Identity.IsAuthenticated)
            
                var requiredRights = String.Format("0-1", context.HttpContext.Request.RouteValues["controller"].ToString(), context.HttpContext.Request.RouteValues["action"].ToString());
                var userName = context.HttpContext.User.Identity.Name;
                if (!String.IsNullOrEmpty(userName))
                
                    
                    var config = context.HttpContext.RequestServices.GetSection<IConfiguration>();
            //Error object does not have defination for GetSection
            string connectionString = config.GetSection("ConnectionStrings:DefaultConnection").Value;
                    
                    var rights = AuthHelper.GetUserRightsByUserName(userName, connectionString);

                    if (!rights.Contains(requiredRights.ToLower()))
                    
                        context.Result = new RedirectResult("~/account/unauthorized");
                    
                
            
            else
            
                context.Result = new RedirectResult("~/account/login");
            
        
        catch (Exception ex)  
        
        
    

控制器:

[CustomAuthorize]
public class UserController : Controller


Startup.cs

public class Startup

    public Startup(IConfiguration configuration)
    
        Configuration = configuration;
    

    public IConfiguration Configuration  get; 

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(o => o.LoginPath = new PathString("/Account/Login")); ;
        services.AddControllersWithViews().AddRazorRuntimeCompilation(); 
        services.AddOptions();
        services.Configure<DataConnection>(Configuration.GetSection("ConnectionStrings"));
        services.AddRepositoryDependency();
        services.AddServiceDependency();
        services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        
        services.AddMvc().AddNToastNotifyToastr(new ToastrOptions()
        
            ProgressBar = false,
            PositionClass = ToastPositions.TopRight
        );
    

    // 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();
        
        else
        
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        
        app.UseNToastNotify();
        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        //app.UseMiddleware<CustomAuthorizeAttribute>();
        app.UseEndpoints(endpoints =>
        
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "controller=Home/action=Index/id?");
        );
    

这里我正在实现基于自定义角色的授权,因此在授权属性中我想获取用户的所有权限并检查用户是否有权访问该操作。在 CustomAuthorize 属性中,我无法获取连接字符串。

尝试使用以下代码获取连接字符串,但抛出错误对象不包含 GetService 的定义。

var configuration = context.HttpContext.RequestServices.GetService(typeof(IConfiguration)); 

 var  connectionstring = configuration.GetService("Connectionstrings:DefaultConnection").Value;

尝试注入 IConfiguration,但我无法在 Controller 上放置属性,因为它希望通过 IConfiguration。

任何帮助都将得到应用。提前致谢。

【问题讨论】:

您可以从context.HttpContext.RequestServices 解析IConfiguration,但不遵循推荐的路线会让您自己变得更难。创建一个授权策略、一个需求,然后为它创建一个处理程序。您可以在处理程序中注入 DbContext 或任何依赖项并允许/拒绝请求。 docs.microsoft.com/en-us/aspnet/core/security/authorization/… 【参考方案1】:

第一种方式,可以使用context.HttpContext.RequestServices获取IConfiguration

using Microsoft.Extensions.DependencyInjection; //be sure add this reference...

public void OnAuthorization(AuthorizationFilterContext context)
            
    try
    
        if (context.HttpContext.User.Identity.IsAuthenticated)
        
            var requiredRights = String.Format("0-1", context.HttpContext.Request.RouteValues["controller"].ToString(), context.HttpContext.Request.RouteValues["action"].ToString());
            var userName = context.HttpContext.User.Identity.Name;
            if (!String.IsNullOrEmpty(userName))
            
                var config = context.HttpContext.RequestServices.GetService<IConfiguration>();
                string connectionString = config.GetSection("ConnectionStrings:DefaultConnection").Value;
                //....
            
        
        else
        
            context.Result = new RedirectResult("~/account/login");
        
    
    catch (Exception ex)
    
    


第二种方式,你可以通过构造函数注入IConfiguration,如下所示:

public class CustomAuthorizeAttribute : Attribute, IAuthorizationFilter

    private readonly string connectionString;

    public CustomAuthorizeAttribute(IConfiguration configuration)
    
        this.connectionString = configuration
                   .GetSection("ConnectionStrings:DefaultConnection").Value;
    
    public void OnAuthorization(AuthorizationFilterContext context)
              
        try
        
            if (context.HttpContext.User.Identity.IsAuthenticated)
            
                var requiredRights = String.Format("0-1", context.HttpContext.Request.RouteValues["controller"].ToString(), context.HttpContext.Request.RouteValues["action"].ToString());
                var userName = context.HttpContext.User.Identity.Name;
                if (!String.IsNullOrEmpty(userName))
                
                    //....
                
            
            else
            
                context.Result = new RedirectResult("~/account/login");
            
        
        catch (Exception ex)
        
        
    

控制器:

[ServiceFilter(typeof(CustomAuthorizeAttribute))]
public class UserController : Controller


注册服务:

services.AddScoped<CustomAuthorizeAttribute>();

【讨论】:

我使用了您的第一种方法,但显示错误对象不包含 GetSection 的定义。我已经使用 Microsoft.Extensions.Configuration 添加了命名空间; 请将您的代码分享给我们。 更新了我的代码,请检查 Startup.cs 添加的代码 这是实现IAuthorize过滤器的正确方法吗?如果我以错误的方式实施,请帮助我采取正确的方法。我不知道为什么我的问题得到-1。非常感谢您的帮助,它使用第二种方法,但我想使用第一种方法。 你确定你使用了正确的代码吗?我看到你用configuration.GetService 代替GetSection,你也说but throwing error object does not contain defination for GetService.。请仔细检查您的代码,确保添加Microsoft.Extensions.Configuration;Microsoft.Extensions.DependencyInjection; 。如果我的回答对你有帮助,你能接受吗?谢谢。

以上是关于如何在 .Net Core MVC 中实现 IAuthorization Filter 时获取连接字符串?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ASP.NET Core 2.2 中实现标识

如何在 ASP.net Core 中实现 dataTables 服务器端分页/搜索/排序

如何在 .NET MVC 2 中实现正确的 HTTP 错误处理?

如何在 ASP.Net MVC 中实现视频文件流式传输?

如何在 ASP.NET MVC 5 中实现自定义身份验证

您将如何在 asp.net mvc 中实现面包屑助手?