diff options
| author | Paul-Christian Volkmer | 2023-04-06 14:42:35 +0200 |
|---|---|---|
| committer | Paul-Christian Volkmer | 2023-04-06 14:42:35 +0200 |
| commit | e0dba6f4ee1550c55e2765adeabf334200984543 (patch) | |
| tree | 2a5829fa2e3ac989f156926ec555ded2e44fd960 | |
| parent | dfbcf3186e6974ef71dfa77b2148f9a8bfe2ce42 (diff) | |
Issue #24: Füge Annotationen und Spring-AOP Aspect zum Absichern von Methodenaufrufen hinzu
| -rw-r--r-- | pom.xml | 6 | ||||
| -rw-r--r-- | src/main/java/DNPM/config/PluginConfiguration.java | 9 | ||||
| -rw-r--r-- | src/main/java/DNPM/security/IllegalSecuredObjectAccessException.java | 13 | ||||
| -rw-r--r-- | src/main/java/DNPM/security/PersonPoolBasedPermissionEvaluator.java | 4 | ||||
| -rw-r--r-- | src/main/java/DNPM/security/PersonPoolSecured.java | 14 | ||||
| -rw-r--r-- | src/main/java/DNPM/security/PersonPoolSecuredResult.java | 14 | ||||
| -rw-r--r-- | src/main/java/DNPM/security/SecurityAspects.java | 74 |
7 files changed, 125 insertions, 9 deletions
@@ -102,6 +102,12 @@ <!-- Test dependencies --> <!-- Wird nur für Unit-tests benoetigt --> <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <version>${spring-version}</version> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.9.2</version> diff --git a/src/main/java/DNPM/config/PluginConfiguration.java b/src/main/java/DNPM/config/PluginConfiguration.java index 654d4c4..0042fe4 100644 --- a/src/main/java/DNPM/config/PluginConfiguration.java +++ b/src/main/java/DNPM/config/PluginConfiguration.java @@ -1,7 +1,6 @@ package DNPM.config; import DNPM.database.SettingsRepository; -import DNPM.security.PersonPoolBasedPermissionEvaluator; import DNPM.services.*; import DNPM.services.consent.ConsentManagerServiceFactory; import DNPM.services.mtb.DefaultMtbService; @@ -13,7 +12,6 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.security.access.PermissionEvaluator; import javax.sql.DataSource; @@ -23,16 +21,11 @@ import javax.sql.DataSource; * @since 0.0.2 */ @Configuration -@ComponentScan(basePackages = "DNPM.analyzer") +@ComponentScan(basePackages = { "DNPM.analyzer", "DNPM.security" }) @EnableJpaRepositories(basePackages = "DNPM.database") public class PluginConfiguration { @Bean - public PermissionEvaluator personBasedPermissionEvaluator(final DataSource dataSource) { - return new PersonPoolBasedPermissionEvaluator(dataSource); - } - - @Bean public FormService formService(final DataSource dataSource) { return new DefaultFormService(dataSource); } diff --git a/src/main/java/DNPM/security/IllegalSecuredObjectAccessException.java b/src/main/java/DNPM/security/IllegalSecuredObjectAccessException.java new file mode 100644 index 0000000..542b604 --- /dev/null +++ b/src/main/java/DNPM/security/IllegalSecuredObjectAccessException.java @@ -0,0 +1,13 @@ +package DNPM.security; + +public class IllegalSecuredObjectAccessException extends RuntimeException { + + public IllegalSecuredObjectAccessException() { + super(); + } + + public IllegalSecuredObjectAccessException(String message) { + super(message); + } + +} diff --git a/src/main/java/DNPM/security/PersonPoolBasedPermissionEvaluator.java b/src/main/java/DNPM/security/PersonPoolBasedPermissionEvaluator.java index 4d895e4..2eac69c 100644 --- a/src/main/java/DNPM/security/PersonPoolBasedPermissionEvaluator.java +++ b/src/main/java/DNPM/security/PersonPoolBasedPermissionEvaluator.java @@ -6,6 +6,7 @@ import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.access.PermissionEvaluator; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.stereotype.Component; import javax.sql.DataSource; import java.io.Serializable; @@ -14,6 +15,7 @@ import java.util.List; /** * Permission-Evaluator zur Auswertung der Berechtigung auf Objekte aufgrund der Personenstammberechtigung */ +@Component public class PersonPoolBasedPermissionEvaluator implements PermissionEvaluator { private final JdbcTemplate jdbcTemplate; @@ -71,7 +73,7 @@ public class PersonPoolBasedPermissionEvaluator implements PermissionEvaluator { var userDetails = (UserDetails)authentication.getPrincipal(); return jdbcTemplate - .query(sql, new Object[]{userDetails.getUsername()}, (rs, rowNum) -> rs.getString("id")); + .query(sql, new Object[]{userDetails.getUsername()}, (rs, rowNum) -> rs.getString("kennung")); } diff --git a/src/main/java/DNPM/security/PersonPoolSecured.java b/src/main/java/DNPM/security/PersonPoolSecured.java new file mode 100644 index 0000000..cac0f78 --- /dev/null +++ b/src/main/java/DNPM/security/PersonPoolSecured.java @@ -0,0 +1,14 @@ +package DNPM.security; + +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) +public @interface PersonPoolSecured { + + PermissionType value() default PermissionType.READ_WRITE; + +} diff --git a/src/main/java/DNPM/security/PersonPoolSecuredResult.java b/src/main/java/DNPM/security/PersonPoolSecuredResult.java new file mode 100644 index 0000000..0ca8edf --- /dev/null +++ b/src/main/java/DNPM/security/PersonPoolSecuredResult.java @@ -0,0 +1,14 @@ +package DNPM.security; + +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) +public @interface PersonPoolSecuredResult { + + PermissionType value() default PermissionType.READ_WRITE; + +} diff --git a/src/main/java/DNPM/security/SecurityAspects.java b/src/main/java/DNPM/security/SecurityAspects.java new file mode 100644 index 0000000..a1fcd3f --- /dev/null +++ b/src/main/java/DNPM/security/SecurityAspects.java @@ -0,0 +1,74 @@ +package DNPM.security; + +import de.itc.onkostar.api.Patient; +import de.itc.onkostar.api.Procedure; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + +import java.util.Arrays; + +@Component +@Aspect +public class SecurityAspects { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private final PersonPoolBasedPermissionEvaluator permissionEvaluator; + + public SecurityAspects(PersonPoolBasedPermissionEvaluator permissionEvaluator) { + this.permissionEvaluator = permissionEvaluator; + } + + @AfterReturning(value = "@annotation(PersonPoolSecuredResult) ", returning = "patient") + public void afterPatient(Patient patient) { + if ( + null != patient + && ! permissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), patient, PermissionType.READ_WRITE) + ) { + logger.warn("Rückgabe von Patient blockiert: {}", patient.getId()); + throw new IllegalSecuredObjectAccessException(); + } + } + + @AfterReturning(value = "@annotation(PersonPoolSecuredResult)", returning = "procedure") + public void afterProcedure(Procedure procedure) { + if ( + null != procedure + && ! permissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), procedure, PermissionType.READ_WRITE) + ) { + logger.warn("Rückgabe von Prozedur blockiert: {}", procedure.getId()); + throw new IllegalSecuredObjectAccessException(); + } + } + + @Before(value = "@annotation(PersonPoolSecured)") + public void beforePatient(JoinPoint jp) { + Arrays.stream(jp.getArgs()) + .filter(arg -> arg instanceof Patient) + .forEach(patient -> { + if (! permissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), patient, PermissionType.READ_WRITE)) { + logger.warn("Zugriff auf Patient blockiert: {}", ((Patient)patient).getId()); + throw new IllegalSecuredObjectAccessException(); + } + }); + } + + @Before(value = "@annotation(PersonPoolSecured)") + public void beforeProcedure(JoinPoint jp) { + Arrays.stream(jp.getArgs()) + .filter(arg -> arg instanceof Procedure) + .forEach(procedure -> { + if (! permissionEvaluator.hasPermission(SecurityContextHolder.getContext().getAuthentication(), procedure, PermissionType.READ_WRITE)) { + logger.warn("Zugriff auf Prozedur blockiert: {}", ((Procedure)procedure).getId()); + throw new IllegalSecuredObjectAccessException(); + } + }); + } + +} |
