From 8dfe158769c69293f852df30282d48bd35477438 Mon Sep 17 00:00:00 2001 From: tliero Date: Wed, 2 Mar 2016 16:23:49 +0100 Subject: [PATCH] API design with Spring Security, pt. 1 --- pom.xml | 4 +-- .../transactions/SecurityConfiguration.java | 34 +++++++++++++++++++ .../repository/AccountRepository.java | 19 +++++++++++ .../repository/CategoryRepository.java | 22 ++++++++++++ .../repository/TransactionRepository.java | 6 ++++ .../repository/UserRepository.java | 17 ++++++++-- src/main/resources/data-h2.sql | 12 ++++--- 7 files changed, 104 insertions(+), 10 deletions(-) create mode 100644 src/main/java/de/tilman/transactions/SecurityConfiguration.java diff --git a/pom.xml b/pom.xml index b55f960..daf68c6 100644 --- a/pom.xml +++ b/pom.xml @@ -24,10 +24,10 @@ com.h2database h2 - + diff --git a/src/main/java/de/tilman/transactions/SecurityConfiguration.java b/src/main/java/de/tilman/transactions/SecurityConfiguration.java new file mode 100644 index 0000000..689528d --- /dev/null +++ b/src/main/java/de/tilman/transactions/SecurityConfiguration.java @@ -0,0 +1,34 @@ +package de.tilman.transactions; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +@EnableGlobalMethodSecurity(prePostEnabled = true) +@EnableWebSecurity +public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.inMemoryAuthentication() + .withUser("Adam").password("test").roles("USER", "ADMIN").and() + .withUser("Betty").password("test").roles("USER"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // Basis-Schutz: Nur autorisierte Zugriffe (feingranulare Steuerung über Assertions) + http.authorizeRequests() + //.antMatchers(HttpMethod.GET, "/public/**").permitAll() + .anyRequest().authenticated(); + + http.httpBasic(); + //http.formLogin(); + + http.csrf().disable(); + } +} diff --git a/src/main/java/de/tilman/transactions/repository/AccountRepository.java b/src/main/java/de/tilman/transactions/repository/AccountRepository.java index 1dbde79..2cf1250 100644 --- a/src/main/java/de/tilman/transactions/repository/AccountRepository.java +++ b/src/main/java/de/tilman/transactions/repository/AccountRepository.java @@ -1,8 +1,27 @@ package de.tilman.transactions.repository; +import java.util.List; + +import org.springframework.data.domain.Page; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; +import org.springframework.security.access.prepost.PreAuthorize; import de.tilman.transactions.domain.Account; public interface AccountRepository extends CrudRepository { + + // http://localhost:8080/accounts/search/findByUserName?username=Betty + @Query("SELECT a FROM Account a INNER JOIN a.users u WHERE u.name = :username") + @PreAuthorize("isFullyAuthenticated() && (#username == principal.username)") // http://stackoverflow.com/q/23640487/3761783 + //@PostFilter("filterObject.user.getId() == principal.id") // http://stackoverflow.com/a/30877376/3761783 + List findByUserName(@Param("username") String username); + + // TODO DELETE auf fremde Accounts möglich? + + @PreAuthorize("hasRole('ROLE_ADMIN')") + @Override + Iterable findAll(); + } diff --git a/src/main/java/de/tilman/transactions/repository/CategoryRepository.java b/src/main/java/de/tilman/transactions/repository/CategoryRepository.java index 22161ea..932f08b 100644 --- a/src/main/java/de/tilman/transactions/repository/CategoryRepository.java +++ b/src/main/java/de/tilman/transactions/repository/CategoryRepository.java @@ -1,9 +1,31 @@ package de.tilman.transactions.repository; +import java.util.List; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.repository.query.Param; +import org.springframework.security.access.prepost.PreAuthorize; import de.tilman.transactions.domain.Category; public interface CategoryRepository extends PagingAndSortingRepository { + + // TODO How to prevent users from retrieving/changing categories of other user's accounts? + // http://localhost:8080/categories/search/findByAccountIdOrderByPositionAsc?accountId=1 + List findByAccountIdOrderByPositionAsc(@Param("accountId") Long accountId); + + @PreAuthorize("hasRole('ROLE_ADMIN')") + @Override + Category save(Category user); + + @PreAuthorize("hasRole('ROLE_ADMIN')") + @Override + void delete(Category user); + + @PreAuthorize("hasRole('ROLE_ADMIN')") + @Override + Page findAll(Pageable pageable); } diff --git a/src/main/java/de/tilman/transactions/repository/TransactionRepository.java b/src/main/java/de/tilman/transactions/repository/TransactionRepository.java index 8d8a687..390cb2d 100644 --- a/src/main/java/de/tilman/transactions/repository/TransactionRepository.java +++ b/src/main/java/de/tilman/transactions/repository/TransactionRepository.java @@ -1,9 +1,15 @@ package de.tilman.transactions.repository; +import org.springframework.data.domain.Page; import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.data.rest.core.annotation.RestResource; import de.tilman.transactions.domain.Transaction; public interface TransactionRepository extends PagingAndSortingRepository { + @RestResource(exported = false) + @Override + Page findAll(); + } diff --git a/src/main/java/de/tilman/transactions/repository/UserRepository.java b/src/main/java/de/tilman/transactions/repository/UserRepository.java index 07a26e8..82d06c6 100644 --- a/src/main/java/de/tilman/transactions/repository/UserRepository.java +++ b/src/main/java/de/tilman/transactions/repository/UserRepository.java @@ -1,13 +1,24 @@ package de.tilman.transactions.repository; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.repository.PagingAndSortingRepository; +import org.springframework.security.access.prepost.PreAuthorize; import de.tilman.transactions.domain.User; public interface UserRepository extends PagingAndSortingRepository { -// @Override -// @PreAuthorize("hasRole('ROLE_ADMIN')") -// public Page findAll(Pageable pageable); + @PreAuthorize("hasRole('ROLE_ADMIN')") + @Override + User save(User user); + + @PreAuthorize("hasRole('ROLE_ADMIN')") + @Override + void delete(User user); + + @Override + @PreAuthorize("hasRole('ROLE_ADMIN')") + public Page findAll(Pageable pageable); } \ No newline at end of file diff --git a/src/main/resources/data-h2.sql b/src/main/resources/data-h2.sql index a1dbe46..68a8cad 100644 --- a/src/main/resources/data-h2.sql +++ b/src/main/resources/data-h2.sql @@ -1,11 +1,12 @@ -INSERT INTO User (id, name) VALUES (1, 'Tilman'), (2, 'Anica'); -INSERT INTO Account (id, name, owner_id) VALUES (1, 'Gemeinschaftskonto', 1), (2, 'Konto Tilman', 1); +INSERT INTO User (id, name) VALUES (1, 'Adam'), (2, 'Betty'); +INSERT INTO Account (id, name, owner_id) VALUES (1, 'Gemeinschaftskonto', 1), (2, 'Konto Adam', 1); INSERT INTO Category (id, name, account_id, position) VALUES (1, 'Essen - Lebensmittel', 1, 2), (2, 'Einnahmen - Gehalt', 1, 1), (3, 'Essen - Arbeit', 1, 3), (4, 'Einnahmen - Gehalt', 2, 1), (5, 'Technik - Server und Hosting', 2, 2); INSERT INTO Account_User (account_id, user_id) VALUES (1, 1), (1, 2), (2, 1); +/* INSERT INTO Transaction (id, amount, account_id, category_id, date, description, creditor_id) VALUES (NULL, 1280.81, 1, 1, '2014-06-01', 'Gehalt', null), (NULL, -2.21, 1, 2, '2014-06-10', 'Brot', null), @@ -16,10 +17,10 @@ INSERT INTO Transaction (id, amount, account_id, category_id, date, description, (NULL, -4.50, 1, 3, '2014-06-20', 'Currywurst', null), (NULL, -4.50, 2, 3, '2014-06-20', 'Currywurst', null), (NULL, -4.09, 1, 3, '2014-06-18', 'Currywurst-Frühstück', null), - (NULL, -4.90, 1, 3, '2014-06-18', 'Currywurst (Auslage Anica)', 2), - (NULL, -8.90, 1, 3, '2014-06-18', 'Curry beim Inder (Auslage Tilman)', 1), + (NULL, -4.90, 1, 3, '2014-06-18', 'Currywurst (Auslage Betty)', 2), + (NULL, -8.90, 1, 3, '2014-06-18', 'Curry beim Inder (Auslage Adam)', 1), (NULL, -12.00, 2, 3, '2014-06-18', 'Curry Thai', null), - (NULL, 1340.22, 2, 4, '2014-06-02', 'Gehalt Tilman', null), + (NULL, 1340.22, 2, 4, '2014-06-02', 'Gehalt Adam', null), (NULL, -12.90, 2, 5, '2014-06-16', 'Host Europe', null); @@ -27,3 +28,4 @@ INSERT INTO Transaction (id, amount, account_id, category_id, date, description, INSERT INTO Transaction (id, amount, account_id, category_id, date, description, creditor_id) VALUES (NULL, -1.50, 1, 2, CURRENT_TIMESTAMP(), 'Transaction', null); Commit; INSERT INTO Transaction (id, amount, account_id, category_id, date, description, creditor_id) VALUES (NULL, -1.50, 1, 3, CURRENT_TIMESTAMP(), 'Transaction', null); Commit; INSERT INTO Transaction (id, amount, account_id, category_id, date, description, creditor_id) VALUES (NULL, 1.50, 1, 4, CURRENT_TIMESTAMP()+1, 'LAST Transaction', null); Commit; +*/ \ No newline at end of file