API design with Spring Security, pt. 1

This commit is contained in:
2016-03-02 16:23:49 +01:00
parent b6fc5edc17
commit 8dfe158769
7 changed files with 104 additions and 10 deletions
+2 -2
View File
@@ -24,10 +24,10 @@
<groupId>com.h2database</groupId> <groupId>com.h2database</groupId>
<artifactId>h2</artifactId> <artifactId>h2</artifactId>
</dependency> </dependency>
<!-- dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId> <artifactId>spring-boot-starter-security</artifactId>
</dependency --> </dependency>
</dependencies> </dependencies>
<properties> <properties>
@@ -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();
}
}
@@ -1,8 +1,27 @@
package de.tilman.transactions.repository; 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.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.security.access.prepost.PreAuthorize;
import de.tilman.transactions.domain.Account; import de.tilman.transactions.domain.Account;
public interface AccountRepository extends CrudRepository<Account, Long> { public interface AccountRepository extends CrudRepository<Account, Long> {
// 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<Account> findByUserName(@Param("username") String username);
// TODO DELETE auf fremde Accounts möglich?
@PreAuthorize("hasRole('ROLE_ADMIN')")
@Override
Iterable<Account> findAll();
} }
@@ -1,9 +1,31 @@
package de.tilman.transactions.repository; 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.PagingAndSortingRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.security.access.prepost.PreAuthorize;
import de.tilman.transactions.domain.Category; import de.tilman.transactions.domain.Category;
public interface CategoryRepository extends PagingAndSortingRepository<Category, Long> { public interface CategoryRepository extends PagingAndSortingRepository<Category, Long> {
// TODO How to prevent users from retrieving/changing categories of other user's accounts?
// http://localhost:8080/categories/search/findByAccountIdOrderByPositionAsc?accountId=1
List<Category> 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<Category> findAll(Pageable pageable);
} }
@@ -1,9 +1,15 @@
package de.tilman.transactions.repository; package de.tilman.transactions.repository;
import org.springframework.data.domain.Page;
import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.data.rest.core.annotation.RestResource;
import de.tilman.transactions.domain.Transaction; import de.tilman.transactions.domain.Transaction;
public interface TransactionRepository extends PagingAndSortingRepository<Transaction, Long> { public interface TransactionRepository extends PagingAndSortingRepository<Transaction, Long> {
@RestResource(exported = false)
@Override
Page<Transaction> findAll();
} }
@@ -1,13 +1,24 @@
package de.tilman.transactions.repository; 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.data.repository.PagingAndSortingRepository;
import org.springframework.security.access.prepost.PreAuthorize;
import de.tilman.transactions.domain.User; import de.tilman.transactions.domain.User;
public interface UserRepository extends PagingAndSortingRepository<User, Long> { public interface UserRepository extends PagingAndSortingRepository<User, Long> {
// @Override @PreAuthorize("hasRole('ROLE_ADMIN')")
// @PreAuthorize("hasRole('ROLE_ADMIN')") @Override
// public Page<User> findAll(Pageable pageable); User save(User user);
@PreAuthorize("hasRole('ROLE_ADMIN')")
@Override
void delete(User user);
@Override
@PreAuthorize("hasRole('ROLE_ADMIN')")
public Page<User> findAll(Pageable pageable);
} }
+7 -5
View File
@@ -1,11 +1,12 @@
INSERT INTO User (id, name) VALUES (1, 'Tilman'), (2, 'Anica'); INSERT INTO User (id, name) VALUES (1, 'Adam'), (2, 'Betty');
INSERT INTO Account (id, name, owner_id) VALUES (1, 'Gemeinschaftskonto', 1), (2, 'Konto Tilman', 1); 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 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 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 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, 1280.81, 1, 1, '2014-06-01', 'Gehalt', null),
(NULL, -2.21, 1, 2, '2014-06-10', 'Brot', 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, 1, 3, '2014-06-20', 'Currywurst', null),
(NULL, -4.50, 2, 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.09, 1, 3, '2014-06-18', 'Currywurst-Frühstück', null),
(NULL, -4.90, 1, 3, '2014-06-18', 'Currywurst (Auslage Anica)', 2), (NULL, -4.90, 1, 3, '2014-06-18', 'Currywurst (Auslage Betty)', 2),
(NULL, -8.90, 1, 3, '2014-06-18', 'Curry beim Inder (Auslage Tilman)', 1), (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, -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); (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, 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, 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; 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;
*/