今天,我们将讨论Web(以及(可能不仅是))应用程序中的安全性。在介绍这些方法和框架之前,我会告诉您一些背景知识。
背景
在IT领域多年的工作中,我不得不处理各个领域的项目。每个项目都有自己的安全要求。如果就身份验证而言,所有方面在要求方面或多或少都相同,那么事实证明,实施授权机制的方法因项目而异。每次,几乎都必须从头开始针对项目的特定目标编写授权,开发体系结构解决方案,然后根据不断变化的需求,测试等进行修改。 -所有这是开发中无法避免的通用过程。随着下一个这样的体系结构方法的每次实现,越来越多的人感觉会出现某种通用方法,该方法将涵盖授权的主要目的并且可以在其他应用程序中重用。本文将以开发的示例为例,考虑一种通用的架构授权方法。框架。
创建框架的方法
像往常一样,在开发新东西之前,您需要确定要解决的问题,该框架将如何方便和有用,并且也许已经有现成的解决方案(我们将在后面讨论)。
每个人都知道两种编码样式-命令式和声明式。当务之急风格描述如何得到结果,声明式的描述了你想要得到的结果。
声明式样式很方便,因为它花费最少的精力和时间来指示所需的结果。例如,对于授权,这可以通过描述用于访问资源,权限等的用户角色的形式来完成。
但是,声明式的样式并不能解决所有问题(至少出于授权目的),实际上并不能解决。命令式样式很方便,因为它为实现提供了必要的灵活性。例如(在授权中)将如何实现为用户分配权限的机制-静态或动态地取决于用户。
, , . , , — . : , , — , .
:
- — , ..
- —
: ( xml, yaml, properties), java annotations.
, , :
- Java annotations java, JVM, runtime, compile time.
- , .. .
- , .. java.
:
- , ( , Admin, Viewer, Editor)
- , (permissions) ( , .. )
- , ( actions) ( ), .. , ( ) , , ( create, modify, delete). , . action-based , — , , , .
. , . .
, java annotations . — .. . Java Annotation Processing, .
Java Module System, Oracle, JDK 9, .
:
- , , , , , .. .
- (actions)
- , ()
- ( ) ()
- () — , ,
Easy-ABAC Framework
.
Spring Boot .
( maven):
<dependency>
<groupId>com.exadel.security</groupId>
<artifactId>easy-abac</artifactId>
<version>1.1</version>
</dependency>
1.1.
, :
@SpringBootApplication
@Import(AbacConfiguration.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
1.
, :
:
(, , , .. — ).
:
import com.exadel.easyabac.model.core.Action;
public enum ProjectAction implements Action {
VIEW,
UPDATE,
CLOSE,
DELETE
}
- com.exadel.easyabac.model.core.Action. enum — .
, enum () , — , .
2.
- :
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface ProjectId {
}
.
:
import com.exadel.easyabac.model.annotation.Access;
import com.exadel.easyabac.model.validation.EntityAccessValidator;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Access(identifier = ProjectId.class)
public @interface ProjectAccess {
ProjectAction[] actions();
Class<? extends EntityAccessValidator> validator();
}
actions validator , :
Error:(13, 9) java: value() method is missing for @com.example.abac.model.ProjectAccess
Error:(13, 9) java: validator() method is missing for @com.example.abac.model.ProjectAccess
@Target({ElementType.METHOD, ElementType.TYPE})
, — instance- .
3.
:
import com.exadel.easyabac.model.validation.EntityAccessValidator;
import com.exadel.easyabac.model.validation.ExecutionContext;
import com.example.abac.model.ProjectAction;
import org.springframework.stereotype.Component;
@Component
public class ProjectValidator implements EntityAccessValidator<ProjectAction> {
@Override
public void validate(ExecutionContext<ProjectAction> context) {
// here get current user actions
// and compare them with context.getRequiredActions()
}
}
( ):
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Access(identifier = ProjectId.class)
public @interface ProjectAccess {
ProjectAction[] value();
Class<? extends EntityAccessValidator> validator() default ProjectValidator.class;
}
:
@ProjectAccess(value = ProjectAction.VIEW, validator = ProjectValidator.class)
4.
, :
import com.exadel.easyabac.model.annotation.ProtectedResource;
import com.example.abac.Project;
import com.example.abac.model.ProjectAccess;
import com.example.abac.model.ProjectAction;
import com.example.abac.model.ProjectId;
import org.springframework.web.bind.annotation.*;
@RestController
@ProtectedResource
@RequestMapping("/project/{projectId}")
public class ProjectController {
@GetMapping
@ProjectAccess(ProjectAction.VIEW)
public Project getProject(@ProjectId @PathVariable("projectId") Long projectId) {
Project project = ...; // get project here
return project;
}
@PostMapping
@ProjectAccess({ProjectAction.VIEW, ProjectAction.UPDATE})
public Project updateProject(@ProjectId @PathVariable("projectId") Long projectId) {
Project project = ...; // update project here
return project;
}
@PostMapping("/close")
@ProjectAccess(ProjectAction.CLOSE)
public Project updateProject(@ProjectId @PathVariable("projectId") Long projectId) {
Project project = ...; // close project here
return project;
}
@DeleteMapping
@ProjectAccess(ProjectAction.DELETE)
public Project updateProject(@ProjectId @PathVariable("projectId") Long projectId) {
Project project = ...; // delete project here
return project;
}
}
@ProtectedResource , — instance- @Access-based , — .
@PublicResource , , , @ProtectedResource
, , . , ( ).
5.
. . , , — -.
, EntityAccessValidator, validate:
public void validate(ExecutionContext<Action> context);
ExecutionContext - : context.getRequiredActions() Action, .
Action — — . Action(s) : , ...
2 Actions — , — Action — . exception, , AccessDeniedException ExceptionHandler HTTP status 403 — .
, - , , - . , , :
: Apache Shiro, JAAS, Spring Security.
Apache Shiro JAAS , , JAAS , Apache Shiro — — , ,
Spring Security — ( ), , compile-time. . , .
Easy-ABAC Framework , , — ...
, . " " .
spring-based . Spring.
.
C
- Java
- Spring-based
本文讨论了Easy-ABAC框架提出的授权体系结构方法。
已开发框架的优点包括:
- 声明式授权样式
- 在编译时处理配置错误
- 简单直接的配置
- 灵活性