【问题标题】:get values from class and method attribute in middleware in asp.net core从asp.net核心中间件中的类和方法属性中获取值
【发布时间】:2021-01-10 23:25:16
【问题描述】:

是否可以在页面加载之前从中间件中的属性获取数据? 这意味着如果我将属性附加到控制器,我可以访问中间件中的数据吗?

我现在为空属性:

public sealed class Secure : Attribute
{
    public Secure()
    {

    }

    public Secure(params string[] roles)
    {

    }
}

【问题讨论】:

  • 这只是为了授权吗?看看AuthorizeAttributeIAuthorizationFilterIAsyncAuthorizationFilter

标签: c# asp.net-core middleware


【解决方案1】:

我认为您最好自定义 ActionFilterAttribute 以在操作执行之前获取数据:

public class SecureAttribute : ActionFilterAttribute
{
    private readonly UserManager<ApplicationUser> _userManager;
    public SecureAttribute(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        //get data from query string
        if (context.ActionArguments.TryGetValue("returnUrl", out object value))
        {
            //returnUrl is the query string key name
            var query = value.ToString();
        }
        //get data from form
        if (context.ActionArguments.TryGetValue("test", out object model))
        {
            var data = model;  
        }
        //get data from log in User
        var USER = context.HttpContext.User;
        if(USER.Identity.IsAuthenticated)
        {
            var user =  _userManager.FindByNameAsync(USER.Identity.Name).Result;
            var roles = _userManager.GetRolesAsync(user).Result;
        }
        base.OnActionExecuting(context);
    }
}

控制器:

[ServiceFilter(typeof(SecureAttribute))]
public async Task<IActionResult> Index(string returnUrl)
{...}

[HttpPost]
[ServiceFilter(typeof(SecureAttribute))]
public IActionResult Index(Test test)
{
    return View(test);
}

Startup.cs:

services.AddScoped<SecureAttribute>();

如果您使用身份获取角色,请务必注册如下服务:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("YourConnectionString")));
   
    services.AddIdentity<IdentityUser, IdentityRole>()
            .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddScoped<SecureAttribute>();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

结果:

【讨论】:

  • 是否可以将参数传递给 ActionFilter?
  • 参数来自哪里?在我的回答中,我可以从查询字符串或表单或登录用户中获取参数。
  • 我必须能够定义用户必须拥有哪些角色才能访问。原来的身份系统不符合我的要求,所以我正在尝试创建自己的身份系统。我需要一个可以由多个应用程序共享的系统,但原来的系统似乎只专注于一个站点。如果这有意义
  • 看起来你想要的是类似于 ASP.NET Core 中基于角色的授权?永远不需要自定义任何属性,默认的授权属性可能会限制身份中的角色访问。如果你必须自定义你的自己的。你可以看到我的回答可以成功获取用户角色。我的回答有什么问题吗?
【解决方案2】:

我最终实现了一个 ActionFilterAttribute。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class SecureAttribute : ActionFilterAttribute
{
    private readonly string[] _roles;

    public SecureAttribute()
    {
        _roles = new string[0];
    }

    public SecureAttribute(params string[] roles)
    {
        _roles = roles;
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        ISecureRepo repo = (ISecureRepo)context.HttpContext.RequestServices.GetService(typeof(ISecureRepo));
        IUserProcessResult user = repo.GetCurrentUserAsync().Result;
        UnauthorizedObjectResult unauth = new UnauthorizedObjectResult($"{StatusCodes.Status401Unauthorized} Unauthorized");

        if (!user.Null())
        {
            bool access = true;

            foreach (string role in this.Roles) 
            { 
                if (user.User.Features.Where(ft => ft.Feature.Name == role).Count() == 0)
                {
                    access = false;
                }
            }

            if (!access)
            {
                context.Result = unauth;
            }
        }
        else
        {
            context.Result = unauth;
        }
    }

    public IEnumerable<string> Roles => _roles;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-16
    • 2017-01-13
    • 2017-07-27
    • 1970-01-01
    • 2012-10-12
    • 2015-06-03
    • 1970-01-01
    • 2018-03-11
    相关资源
    最近更新 更多