gpt4 book ai didi

asp.net - 如何重写代码以在 Asp Net Web Api 中使用具有依赖注入(inject)的 IAuthorizationFilter 而不是具有服务位置的 AuthorizeAttribute?

转载 作者:行者123 更新时间:2023-12-02 12:54:40 25 4
gpt4 key购买 nike

我有自定义的AuthorizeAttribute,在授予用户查看资源的权限之前,我需要使用业务层服务之一来验证数据库中的某些数据。为了能够在我的 AuthorizeAttribute 中分配此服务,我决定使用服务位置“反模式”,代码如下:

internal class AuthorizeGetGroupByIdAttribute : AuthorizeAttribute
{
private readonly IUserGroupService _userGroupService;

public AuthorizeGetGroupByIdAttribute()
{
_userGroupService = ServiceLocator.Instance.Resolve<IUserGroupService>();
}

//In this method I'm validating whether the user is a member of a group.
//If they are not they won't get a permission to view the resource, which is decorated with this attribute.
protected override bool IsAuthorized(HttpActionContext actionContext)
{
Dictionary<string, string> parameters = actionContext.Request.GetQueryNameValuePairs().ToDictionary(x => x.Key, x => x.Value);
int groupId = int.Parse(parameters["groupId"]);
int currentUserId = HttpContext.Current.User.Identity.GetUserId();

return _userGroupService.IsUserInGroup(currentUserId, groupId);
}

protected override void HandleUnauthorizedRequest(HttpActionContext actionContex)
{
if (!HttpContext.Current.User.Identity.IsAuthenticated)
{
base.HandleUnauthorizedRequest(actionContex);
}
else
{
actionContex.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
}
}
}

我的应用程序中有几个类似的其他属性。使用服务定位器可能不是一个好方法。在网上搜索了一下后,我发现有些人建议使用 IAuthorizationFilter 进行依赖注入(inject)。但我不知道如何编写这种IAuthorizationFilter。您能帮我编写 IAuthorizationFilter 来执行与上面的 AuthorizeAttribute 相同的操作吗?

最佳答案

经过一段时间的努力,我想我已经解决了这个问题。为此,您必须执行以下步骤:

1) 首先,您必须使 GetGroupByIdAttribute 成为被动属性,我所说的被动属性是指一个空属性,其中没有任何逻辑(它将严格用于装饰目的)

public class GetGroupByIdAttribute : Attribute
{
}

2) 然后,您必须使用此属性标记要为其添加授权的 Controller 方法。

[HttpPost]
[GetGroupById]
public IHttpActionResult GetGroupById(int groupId)
{
//Some code
}

3) 为了编写您自己的 IAuthorizationFilter,您必须实现其方法 ExecuteAuthorizationFilterAsync。这是完整的类(class)(我添加了注释来指导您完成代码):

public class GetGroupByIdAuthorizationFilter : IAuthorizationFilter
{
public bool AllowMultiple { get; set; }

private readonly IUserGroupService _userGroupService;

//As you can see I'm using a constructor injection here
public GetGroupByIdAuthorizationFilter(IUserGroupService userGroupService)
{
_userGroupService = userGroupService;
}

public Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
{
//First I check whether the method is marked with the attribute, if it is then check whether the current user has a permission to use this method
if (actionContext.ActionDescriptor.GetCustomAttributes<GetGroupByIdAttribute>().SingleOrDefault() != null)
{
Dictionary<string, string> parameters = actionContext.Request.GetQueryNameValuePairs().ToDictionary(x => x.Key, x => x.Value);
int groupId = int.Parse(parameters["groupId"]);
int currentUserId = HttpContext.Current.User.Identity.GetUserId();

//If the user is not allowed to view view the resource, then return 403 status code forbidden
if (!_userGroupService.IsUserInGroup(currentUserId, groupId))
{
return Task.FromResult(new HttpResponseMessage(HttpStatusCode.Forbidden));
}
}
//If this line was reached it means the user is allowed to use this method, so just return continuation() which basically means continue processing
return continuation();
}
}

4) 最后一步是在 WebApiConfig 中注册您的过滤器。

public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Here I am registering Dependency Resolver
config.DependencyResolver = ServiceLocator.Instance.DependencyResolver;

//Then I resolve the service I want to use (which should be fine because this is basically the start of the application)
var userGroupService = ServiceLocator.Instance.Resolve<IUserGroupService>();

//And finally I'm registering the IAuthorizationFilter I created
config.Filters.Add(new GetGroupByIdAuthorizationFilter(userGroupService));

// Web API routes
config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}

现在,如果需要,我可以创建其他使用 IUserGroupServiceIActionFilters,然后在应用程序启动时从 WebApiConfig 注入(inject)此服务> 类,进入所有过滤器。

关于asp.net - 如何重写代码以在 Asp Net Web Api 中使用具有依赖注入(inject)的 IAuthorizationFilter 而不是具有服务位置的 AuthorizeAttribute?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44143206/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com