【问题标题】:How to get connectionstring in implementing IAuthorization Filter in .Net Core MVC?如何在 .Net Core MVC 中实现 IAuthorization Filter 时获取连接字符串?
【发布时间】: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/…

标签: c# asp.net-core .net-core-3.1


【解决方案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; 。如果我的回答对你有帮助,你能接受吗?谢谢。
猜你喜欢
  • 2016-12-17
  • 2019-04-21
  • 1970-01-01
  • 1970-01-01
  • 2017-03-06
  • 1970-01-01
  • 2019-01-07
  • 1970-01-01
相关资源
最近更新 更多