Pendekatan arsitektural untuk otorisasi dalam aplikasi server: Kerangka Kerja Kontrol Akses Berbasis Aktivitas

Hari ini kita akan berbicara tentang keamanan di web (dan, mungkin, tidak hanya) aplikasi. Sebelum menjelaskan pendekatan dan kerangka kerja, saya akan memberi tahu Anda sedikit latar belakang.



Latar Belakang



Selama bertahun-tahun bekerja di bidang TI, saya harus menangani proyek di berbagai bidang. Setiap proyek memiliki persyaratan keamanannya sendiri. Jika dalam hal otentikasi semuanya kurang lebih sama dalam hal persyaratan, maka cara penerapan mekanisme otorisasi ternyata sangat berbeda dari proyek ke proyek. Setiap kali, otorisasi harus ditulis hampir dari awal untuk tujuan spesifik proyek, untuk mengembangkan solusi arsitektural, kemudian menyempurnakannya dengan persyaratan yang berubah, pengujian, dll. - semua ini adalah proses umum yang tidak dapat dihindari dalam pembangunan. Dengan setiap penerapan pendekatan arsitektural berikutnya, semakin banyak perasaan bahwa Anda bisa menghasilkan semacam pendekatan umum yang akan mencakup tujuan utama otorisasi dan yang dapat digunakan kembali dalam aplikasi lain.Artikel ini akan mempertimbangkan pendekatan arsitektur umum untuk otorisasi menggunakan contoh yang dikembangkankerangka .



Pendekatan untuk membuat kerangka kerja



Seperti biasa, sebelum mengembangkan sesuatu yang baru, Anda perlu memutuskan masalah apa yang akan diselesaikan, bagaimana kerangka kerja akan nyaman dan berguna, dan, mungkin, sudah ada solusi yang siap pakai (kita akan membicarakannya nanti).



Semua orang tahu dua gaya pengkodean - imperatif dan deklaratif. Gaya imperatif menjelaskan cara mendapatkan hasil, gaya deklaratif menjelaskan apa yang ingin Anda peroleh sebagai hasil.



, , . , , (permissions) ..

( ) , . , . ( ), — , .



, , . , , — . : , , — , .





:



  1. — , ..




: ( xml, yaml, properties), java annotations.

, , :



  1. Java annotations java, JVM, runtime, compile time.
  2. , .. .
  3. , .. 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);
    }
}


Project . , .



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:



@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



  1. Java
  2. Spring-based




Artikel ini membahas pendekatan arsitektur untuk otorisasi, yang disajikan oleh Easy-ABAC Framework.

Di antara keunggulan kerangka yang dikembangkan adalah:



  1. Gaya otorisasi deklaratif
  2. Menangani kesalahan konfigurasi pada waktu kompilasi
  3. Konfigurasi sederhana dan mudah
  4. Fleksibilitas



All Articles