将授权置于服务层而非Web API层 [英] Placing authorization into the service layer rather than Web API layer

查看:137
本文介绍了将授权置于服务层而非Web API层的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用.NET Core Web API构建REST API.

I'm building out a REST API with .NET Core Web API.

我的控制器只是将请求转发到服务层并返回结果

My controllers simply forward requests to the service layer and return the result

[HttpPost(nameof(Create))]
public async Task<Response<ProviderDTO>> Create([FromBody] ProviderDTO provider)
    => await providerService.CreateAsync(provider);

我现在在系统中需要开始实施授权的位置.

I'm at the point in the system now where I need to start implementing authorization.

.NET Core具有很多选项来实现授权,但是文档主要在Web层(控制器显然居住的地方)的上下文中讨论了这些方法.

.NET Core has a lot of options to implement authorization, but the documentation predominantly discusses these approaches in the context of the Web layer (where the controllers obviously live).

我的直觉告诉我,我需要在服务层本身中实现授权,而不是将此授权放置在Web层上.

My instincts are telling me that I need to be implementing the authorization within the service layer itself, rather than placing this authorization on the web layer.

我的某些推理包括:

  1. 服务层可能会被控制器以外的其他事物调用(例如,调用其他服务的服务,此时不会与授权相关).
  2. 服务授权可以直接进行单元测试,而不必依赖为服务前面的每个层"编写集成测试.
  3. 保存对数据库的多次调用-如果我需要在授权要求中对文档进行授权(如果通过),则稍后必须在服务中提取同一文档.

问题一

IPrincipalIAuthorizationService注入我的服务并直接在其中处理授权是否明智?然后,Web层将仅检查用户已登录,也许只是一些基于策略的简单属性(例如,该控制器仅允许员工策略)

Would it be a sensible approach to inject IPrincipal and IAuthorizationService into my services and handle authorization directly in there? Then the web layer would purely just check the user is logged in, and perhaps some simpler policy based attributes (i.e. this controller only allows staff policy for example)

第二个问题

有没有人可以将我链接到任何资源(我做了研究,但是没有太多资源了

Does anyone have any resources they could link me through to (I did research, but there's not much out there on this)

PS:关于服务层中的拒绝请求,我有一个异常处理中间件,该中间件将自定义异常转换为HTTP响应.因此,如果发生未经授权的请求,我将抛出一些未经授权的异常,最终将导致HTTP 403.

PS: Regarding rejecting requests in the service layer, I have an exception handling middleware that converts custom exceptions to HTTP responses. Thus, if an unauthorized request occurs, I will be throwing some for of Unauthorized exception which will ultimately result in a HTTP 403.

推荐答案

这全都取决于我们在谈论哪种授权以及实现该授权需要进行多少工作.

It all depends on what kind of authorization we are talking about and how much work is involved in making it happen.

通常来说,将服务层与Web层混合在一起并不是一个好主意,因此请将它们分开.

Generally speaking it is not a good idea to mix your service layer with the web one so keep them separate.

Web授权是一回事-在这里您说的是我有一个用户,是否允许他访问此端点/页面/任何内容.如果不是这样,则可以通过根本不调用服务层来节省资源,并且可以在过程的早期和非常快速地拒绝Web层中的请求,而不会浪费资源.

Web Authorization is one thing - here you are saying I have a user, is he allowed to access this endpoint / page / whatever. If they are not, you save resources by not even calling the service layer at all and can reject the request in the web layer, very early in the process and very quickly without wasting resources.

接下来,您在说什么服务层?当您从数据层获得数据后,是真正与数据库对话的对象还是进行一些数据操纵的对象?

Next, what is this service layer you are talking about? Is it the one that actually talks to the database or is it the one which does some data manipulation, once you have the data from the data layer?

我的偏好是拥有一个单独的数据层和授权层.授权层是应用所需规则的层,然后返回其结果,以便您知道是否还要获取任何数据.它没有链接到您的Web层,它不返回HTTP代码,并且通常来说与UI无关.

My preference would be to have a separate datalayer and authorization layer. The authorization layer is the one that applies whatever rules you need and then returns the result of it so you know whether to even bother fetching any data or not. It is not linked to your web layer, it does not return HTTP codes and generally speaking has nothing to do with the UI side of things.

这意味着,如果您有多个客户端(例如Web UI和移动UI),则两者都将通过此层,因此不会重复此工作级别.

What this means is that if you have multiple clients, like for example a Web UI and a mobile UI then both will go through this layer so this level of work is not duplicated.

甚至更好的是,您可能希望构建一个负责返回数据的API,然后您要做的就是从任何拥有的客户端处处理这一件事,然后就可以在那里处理您的授权.如果您确定可以单独调用授权层,而又不依赖其他任何层,那么可以从多个地方调用它,并且可以轻松,独立地对其进行测试.

Even better you might want to build a proper API responsible for returning data then all you have to do is deal with this one thing from whatever client you have and you can handle your authorization there. If you make sure you can call your authorization layer separately from anything else and not depending on anything else then you can call it from multiple places and can test it easily and independently.

这是人们在构建任何东西之前都会考虑的事情,一旦完成所有其他操作,安全并不是您最后要添加的东西.在构建产品时要牢记这一点,因为它涉及到很多东西,并且会影响您的体系结构.

This is the kind of thing people think about before building anything, security is not the last thing you add in once everything else is done. You build your product with it in mind as it touches on a lot of things and it will influence your architecture.

有关一切如何组合的图表将有所帮助.

A diagram of how everything fits together would help.

  • 您拥有哪种建筑?
  • 您在谈论这个授权有多涉及?
  • 我们在谈论什么样的客户?

在此方法起作用之前,有很多问题要回答.

There are lots and lots of questions to answer before this can work.

仅需我几点,您就发表了几句话:

Just a couple more points from me, you made a couple of statements :

服务层可能会被控制器以外的其他东西调用 (例如,调用其他服务的服务不会 与授权有关).

Service layer could get called by something other than a controller (for example, services calling other services, which wouldn't be concerned at that point with authorization).

服务授权可以直接进行单元测试,而不必进行 依靠为每个层"编写的集成测试 在服务的前面.

Service authorization can be unit tested directly, rather than having to rely on integration tests being written for each "layer" that goes in front of the services.

  1. 如果您正在考虑微服务(又称许多独立运行的小服务),那么您绝对需要根据这些事物的访问和相互通信方式来关注安全性.

  1. if you are thinking about microservices, aka many little services which function independently then you most definitely need to concern yourself with security depending on how these things are accessed and communicate with each other.

这就是为什么您编写一个授权层,所有内容都经过它的原因,而这就是您在不关心任何UI事物的情况下进行测试的那一层.

that's why you write an authorization layer, everything goes through it and this is the one you test without caring about any UI kind of thing.

这篇关于将授权置于服务层而非Web API层的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆