gpt4 book ai didi

c# - 将当前用户包含在 Controller 对服务层的每次调用中

转载 作者:太空狗 更新时间:2023-10-29 21:56:53 25 4
gpt4 key购买 nike

我在我的 Controller 中执行模型验证,但第二次业务验证需要在服务/业务级别进行。这通常与用户权限有关:当前用户是否有权访问他试图获取或发布的客户/订单信息?

我的第一个(也是可行的)方法是传递整个 User 实例或其 Id(通过调用 User.Identity.GetUserId()),这在大多数情况下(如果不是全部)就足够了。所以我会有这样的东西:

public IHttpActionResult Get(int id)
{
try
{
var customer = customerService.GetById(id, userId);
return Ok(customer);
}
catch (BusinessLogicException e)
{
return CreateErrorResponse(e);
}
}

但我不太喜欢这样一个事实,即使用这种方法我将不得不在几乎每次调用我的服务层时都包含一个额外的参数。如果我正在调用 GetById() 方法,我想通过提供 ID 而不是 ID 用户 ID 来获取某些内容。

一个简单的解决方法是遵循这些思路,这也有效:

public IHttpActionResult Get(int id)
{
customerService.SetCurrentUser(User.Identity.GetUserId());

try
{
var customer = customerService.GetById(id);
return Ok(customer);
}
catch (BusinessLogicException e)
{
return CreateErrorResponse(e);
}
}

但我希望每次调用该服务时都自动完成,而不是必须单独调用来设置当前用户。我该怎么做?

这是我的服务的样子:

public class CustomerService : EntityService<Customer>, ICustomerService
{
public string UserId;
IContext context;
public CustomerService(IContext context) : base(context)
{
this.context = context;
this.dbSet = context.Set<Customer>();
}

public void SetCurrentUser(string userId)
{
UserId = userId;
}

public DTO.Customer GetById(int id)
{
if (!IsAccessibleByUser(id))
{
throw new BusinessLogicException(ErrorCode.UserError, "UserId: " + UserId);
}

return dbSet.FirstOrDefault(x => x.Id == id).ToDto<Customer, DTO.Customer>();
}

public bool IsAccessibleByUser(int id)
{
return context.UsersAPI.Any(a => a.AspNetUsersID == UserId);
}
}

最佳答案

我宁愿在自定义授权过滤器中执行此授权逻辑。如果用户未经过身份验证或授权,则甚至无需访问您的 Controller 操作代码。

例如你可以有这样的东西:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var authorized = base.AuthorizeCore(httpContext);
if (!authorized)
{
return false;
}

var rd = httpContext.Request.RequestContext.RouteData;
// Get the id of the requested resource from the route data
string resourceId = rd.Values["id"] as string;
if (string.IsNullOrEmpty(resourceId))
{
// No id of resource was specified => we do not allow access
return false;
}

string userId = httpContext.User.Identity.GetUserId();
return IsAccessibleByUser(resourceId, userId);
}

private bool IsAccessibleByUser(string resourceId, string userId)
{
// You know what to do here => fetch the requested resource
// from your data store and verify that the current user is
// authorized to access this resource
}
}

然后您可以使用自定义属性装饰需要此类授权的 Controller 或操作:

[MyAuthorize]
public IHttpActionResult Get(int id)
{
try
{
// At this stage you know that the user is authorized to
// access the requested resource
var customer = customerService.GetById(id);
return Ok(customer);
}
catch (BusinessLogicException e)
{
return CreateErrorResponse(e);
}
}

当然,这个自定义属性可以通过使用自定义过滤器提供程序进一步改进,它允许将您的数据上下文注入(inject)其中,以便您可以执行正确的调用。然后你只能有一个标记属性,过滤器提供程序将使用它来决定它是否应该执行授权逻辑。

关于c# - 将当前用户包含在 Controller 对服务层的每次调用中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35792438/

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