如何基于使用批注在REST中创建资源的用户授权特定资源

问题描述:

我不太理解带有保留策略(如RUNTIME)的Java批注.我正在尝试做的是创建一个名为@Authorize的注释,并将其用于需要用户授权才能执行某些操作的用户(此时用户已通过身份验证). 例如.我有一个带有getOrder()方法的订单服务.我只希望创建此订单的用户访问它. `

I do not understand Java annotations with retention policy as RUNTIME that well. What I'm trying to do is create an annotation named @Authorize and use it on methods which needs user authorization in order to perform some action( the user is already authenticated at this point). eg. I have an order service with a getOrder() method. I want only the user who created this order to access it. `

public void getOrder(User user) {
   //current code does something like this
   if(order.getCreatedBy().equals(user)) {
     //then proceed. 
}

} `

我不想将此逻辑与业务逻辑混为一谈.相反,我希望拥有这样的东西- `

I do not want to mix this logic with business logic. Instead, I'm looking to have something like this- `

@Authorize
public void getOrder(User user) {
   //business logic
}

` 有几种方法,但并非所有方法都需要这种授权.有人可以解释一下我如何在这里将它们拼在一起吗? 我现在不了解的是AnnotationProcessor在这里会如何帮助我,因为它在编译时就发挥了魔力.据我了解,它将帮助我在编译时生成一些代码,但是我不知道如何使用该生成的代码.我在AnnotationProcessors上浏览了许多示例,但仍然缺少一些东西. 这些链接到目前为止对我的理解有所帮助-

` There are several methods but not all of them would need such authorization. Could someone please explain me how can I fit the pieces together here? What I don't understand at this point is that how AnnotationProcessor would help me here since it does its magic at compile time. As far as I understand, it will help me generate some code at compile time but I have no clue how to use that generated code. I went through numerous examples on AnnotationProcessors but I'm still missing something. These links helped me a bit to understand annotation processing so far-

http://hannesdorfmann.com/annotation-processing/annotationprocessing101 https://equaleyes.com/blog/2017/09/04/annotation-处理/

即使我接受反射,也应该在哪里放置反射逻辑?会适得其反吗?

Even if I go with reflections, where should I place the reflection logic? and is it counter productive of what I'm trying to achieve?

在这一点上,我也对其他不涉及注释的解决方案持开放态度,但将有助于我使用这种资源特定的授权将业务逻辑分离出来.

At this point, I'm open to other solutions as well which do not involve annotations but will help me separating out business logic with such resource specific authorization.

要在Java中实现对方法的授权控制,我强烈建议带有可扩展访问控制标记语言(XACML)实现的 Spring Security 有一个Spring Security API.

To implement authorization controls on methods in Java, I highly recommend Spring Security with an eXtensible Access Control Markup Language (XACML) implementation that has a Spring Security API.

Spring Security提供了两种主要方法来保护对方法的访问:

Spring Security provides two main means to protect access to methods:

  • 预授权:这允许某些条件/限制 在允许执行该方法之前进行检查.未能 验证这些条件将导致无法致电 方法.
  • 后授权:这允许某些条件/约束 方法返回后进行检查.这是不常使用的 预授权检查,但可用于提供额外的安全性 围绕复杂的互连业务层方法,尤其是 围绕与方法返回的对象有关的约束.
  • Preauthorization: this allows for certain conditions/constraints to be checked before the execution of the method is allowed. Failure to verify these conditions will result in the failure to call the method.
  • Postauthorization: this allows for certain conditions/constraints to be checked after the method returns. This is used less often that preauthorization check, but can be used to provide extra security around complex interconnected business tier methods, especially around constraints related to the object returned by the method.

例如,访问控制规则之一是用户在能够调用方法getEvents()之前具有ROLE_ADMIN权限.在Spring Security框架内完成此操作的方法是使用PreAuthorize批注,如下所示:

Say for example, that one of the access control rule is that the user has have the ROLE_ADMIN authority before being able to invoke a method getEvents(). The way to do that within the Spring Security framework would be to use the PreAuthorize annotation as below:

public interface Sample { ... 
@PostAuthorize("hasRole('ROLE_ADMIN')") 
Event getEvent(); } 

本质上,Spring Security使用运行时面向方面编程(AOP)切入点在方法建议之前执行,如果未满足指定的安全性约束,则抛出o.s.s.access.AccessDeniedException.

In essence Spring Security uses a runtime Aspect Oriented Programming (AOP) pointcut to execute before an advice on the method and throw an o.s.s.access.AccessDeniedException if the security constraints specified are not met.

在此 Spring Security通过基于表达式的访问控制在实现访问控制方面做得很好,但是基于属性的访问控制(ABAC)可以对访问进行更细粒度的控制,这是美国国家标准技术研究院的推荐.

Spring Security does a great job of implementing access control with its expression based access control, but attribute based access control (ABAC) allows more fine grained control of access and is recommended by the National Institute of Standards and Technology.

为解决基于角色的访问控制(RBAC)的局限性,NIST提出了一种称为ABAC(基于属性的访问控制)的新模型.在ABAC中,您现在可以使用更多的元数据/参数.例如,您可以考虑:

To address the limitations of Role Based Access Control (RBAC), NIST came up with a new model called ABAC (Attribute Based Access Control). In ABAC, you can now use more metadata / parameters. You can for instance consider:

  • 用户的身份,角色,职务,位置,部门,日期 出生...
  • 资源的类型,位置,所有者,价值,部门...

  • a user's identity, role, job title, location, department, date of birth...
  • a resource's type, location, owner, value, department...

上下文信息,例如用户在一天中的行动时间 尝试使用资源

contextual information e.g. time of day the action the user is attempting on the resource

所有这些都称为属性.属性是ABAC的基础,因此是名称.您可以将这些属性组合到策略中.政策有点像ABAC的秘密武器.策略可以授予和拒绝访问.例如:

All these are called attributes. Attributes are the foundation of ABAC, hence the name. You can assemble these attributes into policies. Policies are a bit like the secret sauce of ABAC. Policies can grant and deny access. For instance:

  • 如果员工和记录位于同一区域,则该员工可以查看记录
  • 拒绝访问下午5点至早上8点之间的记录.

策略可用于表示高级方案,例如

Policies can be used to express advanced scenarios e.g.

  • 职责分工
  • 基于时间的约束(请参见上文)
  • 基于关系的访问控制(请参见上文)
  • 授权规则委派Bob访问Alice的文档.

有两种主要的语法可用于编写策略:

There are 2 main syntaxes available to write policies:

  • the Abbreviated Language for Authorization (ALFA), which is based on XACML
  • the eXtensible Access Control Markup Language (XACML)

ABAC还带有一个体系结构,用于定义如何评估和执行策略.

ABAC also comes with an architecture to define how the policies will get evaluated and enforced.

该体系结构包含以下组件:

The architecture contains the following components:

  • 策略执行点(PEP):这是 保护您要保护的API/应用程序. PEP拦截 流程,对其进行分析,然后向PDP发送授权请求 (见下文).然后,它收到一个决定(许可/拒绝) 强制执行.

  • the Policy Enforcement Point (PEP): this is the component that secures the API / application you want to protect. The PEP intercepts the flow, analyzes it, and send an authorization request to the PDP (see below). It then receives a decision (Permit/Deny) which it enforces.

策略决策点(PDP)收到授权请求 (例如,Alice可以查看记录#123吗?)并根据集合对其进行评估 配置的策略.最终达到 将其发送回PEP的决定.评估期间 在此过程中,PDP可能需要其他元数据,例如用户的工作 标题.为此,它可以求助于策略信息点(PIP)

the Policy Decision Point (PDP) receives an authorization request (e.g. can Alice view record #123?) and evaluates it against the set of policies it has been configured with. It eventually reaches a decision which it sends back to the PEP. During the evaluation process, the PDP may need additional metadata e.g. a user's job title. To that effect, it can turn to policy information points (PIP)

全面披露-我在XACML技术委员会任职,并为动态授权提供商 Axiomatics 工作.实现XACML.

Full disclosure - I am on the XACML Technical Committee and work for Axiomatics, a provider of dynamic authorization that implements XACML.

Axiomatics为 Axiomatics政策服务器提供了Spring Security SDK,提供了四个表达式,可用于查询PDP,作为保护方法调用的一部分

Axiomatics provides a Spring Security SDK for their Axiomatics Policy Server and it provides four expressions that can be used to query the PDP as a part of protecting a method invocation

  1. xacmlDecisionPreAuthz,用@PreAuthorize
  2. 调用
  3. xacmlDecisionPostAuthz,用@PostAuthorize
  4. 调用
  5. xacmlDecisionPreFilter,用@PostFilter
  6. 调用
  7. xacmlDecisionPostFilter,用@PreFilter
  8. 调用
  1. xacmlDecisionPreAuthz, called with @PreAuthorize
  2. xacmlDecisionPostAuthz, called with @PostAuthorize
  3. xacmlDecisionPreFilter, called with @PostFilter
  4. xacmlDecisionPostFilter, called with @PreFilter

这些方法的确切签名如下:

The exact signatures for these methods are as follows:

  1. xacmlDecisionPreAuthz(Collection<String> attributeCats, Collection<String> attributeTypes, Collection<String> attributeIds, ArrayList<Object> attributeValues)
  2. xacmlDecisionPostAuthz(Collection<String> attributeCats, Collection<String> attributeTypes, Collection<String> attributeIds, ArrayList<Object> attributeValues)
  3. xacmlDecisionPreFilter(Collection<String> attributeCats, Collection<String> attributeTypes, Collection<String> attributeIds, ArrayList<Object> attributeValues)
  4. xacmlDecisionPostFilter (Collection<String> attributeCats, Collection<String> attributeTypes, Collection<String> attributeIds, ArrayList<Object> attributeValues)
  1. xacmlDecisionPreAuthz(Collection<String> attributeCats, Collection<String> attributeTypes, Collection<String> attributeIds, ArrayList<Object> attributeValues)
  2. xacmlDecisionPostAuthz(Collection<String> attributeCats, Collection<String> attributeTypes, Collection<String> attributeIds, ArrayList<Object> attributeValues)
  3. xacmlDecisionPreFilter(Collection<String> attributeCats, Collection<String> attributeTypes, Collection<String> attributeIds, ArrayList<Object> attributeValues)
  4. xacmlDecisionPostFilter (Collection<String> attributeCats, Collection<String> attributeTypes, Collection<String> attributeIds, ArrayList<Object> attributeValues)

对于完整的XACML实现列表,您可以在Wikipedia上查看此列表.