added simultaneous token-based and http basic authentication

This commit is contained in:
Main
2016-02-18 23:57:39 +03:00
parent 99d07667bb
commit d1339729ec
8 changed files with 238 additions and 111 deletions

View File

@@ -2,8 +2,8 @@ package net.chrisrichardson.eventstore.javaexamples.banking.commonauth;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.QuerySideCustomer;
import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.filter.StatelessAuthenticationFilter;
import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
@@ -15,8 +15,10 @@ import org.springframework.security.config.annotation.authentication.builders.Au
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;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.token.KeyBasedPersistenceTokenService;
import org.springframework.security.core.token.TokenService;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
@@ -51,12 +53,15 @@ public class AuthConfiguration extends WebSecurityConfigurerAdapter {
@Override
public UserDetailsService userDetailsServiceBean() {
return email -> {
QuerySideCustomer customer = customerAuthService.findByEmail(email);
/* QuerySideCustomer customer = customerAuthService.findByEmail(email);
if (customer != null) {
return new User(email);
} else {
throw new UsernameNotFoundException(String.format("could not find the customer '%s'", email));
}
}*/
//authorize everyone with basic authentication
return new User(email, "", true, true, true, true,
AuthorityUtils.createAuthorityList("USER"));
};
}

View File

@@ -20,8 +20,9 @@ public class CustomerAuthService {
List<QuerySideCustomer> customers = customerAuthRepository.findByEmail(email);
if (customers.isEmpty())
throw new EmptyResultDataAccessException(1);
else if(customers.size()>1)
throw new IncorrectResultSizeDataAccessException(1, customers.size());
//TODO: add unique email constraint
/* else if(customers.size()>1)
throw new IncorrectResultSizeDataAccessException(1, customers.size());*/
else
return customers.get(0);
}

View File

@@ -0,0 +1,48 @@
package net.chrisrichardson.eventstore.javaexamples.banking.commonauth.utils;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerResponse;
import org.apache.tomcat.util.codec.binary.Base64;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import rx.Observable;
import java.nio.charset.Charset;
/**
* Created by Main on 18.02.2016.
*/
public class BasicAuthUtils {
public static HttpHeaders basicAuthHeaders(String username) {
return new HttpHeaders() {
{
String auth = username + ":";
byte[] encodedAuth = Base64.encodeBase64(
auth.getBytes(Charset.forName("US-ASCII")));
String authHeader = "Basic " + new String(encodedAuth);
set("Authorization", authHeader);
}
};
}
public static <T> T doRestTemplateRequest(RestTemplate restTemplate, String url, HttpMethod httpMethod, Class<T> responseType) {
return doRestTemplateRequest(restTemplate, url, httpMethod, responseType, null);
}
public static <T> T doRestTemplateRequest(RestTemplate restTemplate, String url, HttpMethod httpMethod, Class<T> responseType, Object requestObject) {
HttpEntity httpEntity;
if(requestObject!=null) {
httpEntity = new HttpEntity(requestObject, BasicAuthUtils.basicAuthHeaders("test_user@mail.com"));
} else {
httpEntity = new HttpEntity(BasicAuthUtils.basicAuthHeaders("test_user@mail.com"));
}
return restTemplate.exchange(url,
httpMethod,
httpEntity,
responseType).getBody();
}
}

View File

@@ -1,5 +1,8 @@
package net.chrisrichardson.eventstore.javaexamples.banking.common.customers;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
/**
* Created by popikyardo on 03.02.16.
*/
@@ -31,4 +34,14 @@ public class CustomerResponse {
public void setCustomerInfo(CustomerInfo customerInfo) {
this.customerInfo = customerInfo;
}
@Override
public boolean equals(Object o) {
return EqualsBuilder.reflectionEquals(this, o);
}
@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
}

View File

@@ -8,6 +8,7 @@ dependencies {
testCompile project(":accounts-query-side-web")
testCompile project(":testutil")
testCompile project(":common-auth")
testCompile "junit:junit:4.11"
testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
testCompile scalaTestDependency

View File

@@ -5,6 +5,7 @@ import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.Addr
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerInfo;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerResponse;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.Name;
import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.utils.BasicAuthUtils;
import net.chrisrichardson.eventstore.javaexamples.banking.web.commandside.accounts.CreateAccountRequest;
import net.chrisrichardson.eventstore.javaexamples.banking.web.commandside.accounts.CreateAccountResponse;
import net.chrisrichardson.eventstore.javaexamples.banking.web.commandside.transactions.CreateMoneyTransferRequest;
@@ -15,6 +16,7 @@ import net.chrisrichardson.eventstorestore.javaexamples.testutil.Producer;
import net.chrisrichardson.eventstorestore.javaexamples.testutil.Verifier;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.http.HttpMethod;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;
@@ -81,10 +83,21 @@ public class EndToEndTest {
assertCustomerResponse(customerId, customerInfo);
final CreateAccountResponse fromAccount = restTemplate.postForEntity(accountsCommandSideBaseUrl("/accounts"), new CreateAccountRequest(customerId, "My #1 Account", initialFromAccountBalance), CreateAccountResponse.class).getBody();
final CreateAccountResponse fromAccount = BasicAuthUtils.doRestTemplateRequest(restTemplate,
accountsCommandSideBaseUrl("/accounts"),
HttpMethod.POST,
CreateAccountResponse.class,
new CreateAccountRequest(customerId, "My #1 Account", initialFromAccountBalance)
);
final String fromAccountId = fromAccount.getAccountId();
CreateAccountResponse toAccount = restTemplate.postForEntity(accountsCommandSideBaseUrl("/accounts"), new CreateAccountRequest(customerId, "My #2 Account", initialToAccountBalance), CreateAccountResponse.class).getBody();
CreateAccountResponse toAccount = BasicAuthUtils.doRestTemplateRequest(restTemplate,
accountsCommandSideBaseUrl("/accounts"),
HttpMethod.POST,
CreateAccountResponse.class,
new CreateAccountRequest(customerId, "My #2 Account", initialToAccountBalance)
);
String toAccountId = toAccount.getAccountId();
Assert.assertNotNull(fromAccountId);
@@ -94,8 +107,12 @@ public class EndToEndTest {
assertAccountBalance(toAccountId, initialToAccountBalance);
final CreateMoneyTransferResponse moneyTransfer = restTemplate.postForEntity(transactionsCommandSideBaseUrl("/transfers"),
new CreateMoneyTransferRequest(fromAccountId, toAccountId, amountToTransfer), CreateMoneyTransferResponse.class).getBody();
final CreateMoneyTransferResponse moneyTransfer = BasicAuthUtils.doRestTemplateRequest(restTemplate,
transactionsCommandSideBaseUrl("/transfers"),
HttpMethod.POST,
CreateMoneyTransferResponse.class,
new CreateMoneyTransferRequest(fromAccountId, toAccountId, amountToTransfer)
);
assertAccountBalance(fromAccountId, finalFromAccountBalance);
assertAccountBalance(toAccountId, finalToAccountBalance);
@@ -113,7 +130,10 @@ public class EndToEndTest {
new Producer<GetAccountResponse>() {
@Override
public Observable<GetAccountResponse> produce() {
return Observable.just(restTemplate.getForEntity(accountsQuerySideBaseUrl("/accounts/" + fromAccountId), GetAccountResponse.class).getBody());
return Observable.just(BasicAuthUtils.doRestTemplateRequest(restTemplate,
accountsQuerySideBaseUrl("/accounts/" + fromAccountId),
HttpMethod.GET,
GetAccountResponse.class));
}
},
new Verifier<GetAccountResponse>() {
@@ -130,7 +150,10 @@ public class EndToEndTest {
new Producer<CustomerResponse>() {
@Override
public Observable<CustomerResponse> produce() {
return Observable.just(restTemplate.getForEntity(customersQuerySideBaseUrl("/customers/" + customerId), CustomerResponse.class).getBody());
return Observable.just(BasicAuthUtils.doRestTemplateRequest(restTemplate,
customersQuerySideBaseUrl("/customers/" + customerId),
HttpMethod.GET,
CustomerResponse.class));
}
},
new Verifier<CustomerResponse>() {

View File

@@ -5,6 +5,7 @@ import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.Cust
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.CustomerResponse;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.Name;
import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.model.AuthRequest;
import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.utils.BasicAuthUtils;
import net.chrisrichardson.eventstorestore.javaexamples.testutil.Producer;
import net.chrisrichardson.eventstorestore.javaexamples.testutil.Verifier;
import org.junit.Assert;
@@ -14,6 +15,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.client.RestTemplate;
@@ -42,7 +45,8 @@ public class BankingAuthTest {
@Test
public void shouldCreateCustomerAndLogin() {
CustomerInfo customerInfo = generateCustomerInfo();
String email = uniqueEmail();
CustomerInfo customerInfo = generateCustomerInfo(email);
final CustomerResponse customerResponse = restTemplate.postForEntity(baseUrl("/customers"), customerInfo, CustomerResponse.class).getBody();
final String customerId = customerResponse.getId();
@@ -52,7 +56,7 @@ public class BankingAuthTest {
assertCustomerResponse(customerId, customerInfo);
AuthRequest authRequest = new AuthRequest("current@email.com");
AuthRequest authRequest = new AuthRequest(email);
final CustomerResponse loginCustomerResponse = restTemplate.postForEntity(baseUrl("/login"), authRequest, CustomerResponse.class).getBody();
@@ -64,7 +68,10 @@ public class BankingAuthTest {
new Producer<CustomerResponse>() {
@Override
public Observable<CustomerResponse> produce() {
return Observable.just(restTemplate.getForEntity(baseUrl("/customers/" + customerId), CustomerResponse.class).getBody());
return Observable.just(BasicAuthUtils.doRestTemplateRequest(restTemplate,
baseUrl("/customers/" + customerId),
HttpMethod.GET,
CustomerResponse.class));
}
},
new Verifier<CustomerResponse>() {
@@ -76,10 +83,10 @@ public class BankingAuthTest {
});
}
private CustomerInfo generateCustomerInfo() {
private CustomerInfo generateCustomerInfo(String email) {
return new CustomerInfo(
new Name("John", "Doe"),
"current@email.com",
email,
"000-00-0000",
"1-111-111-1111",
new Address("street 1",
@@ -89,4 +96,8 @@ public class BankingAuthTest {
"1111111")
);
}
private String uniqueEmail() {
return System.currentTimeMillis() + "@email.com";
}
}

View File

@@ -1,11 +1,14 @@
package net.chrisrichardson.eventstore.javaexamples.banking.web;
import net.chrisrichardson.eventstore.javaexamples.banking.common.customers.*;
import net.chrisrichardson.eventstore.javaexamples.banking.commonauth.utils.BasicAuthUtils;
import net.chrisrichardson.eventstore.javaexamples.banking.web.commandside.accounts.CreateAccountRequest;
import net.chrisrichardson.eventstore.javaexamples.banking.web.commandside.accounts.CreateAccountResponse;
import net.chrisrichardson.eventstore.javaexamples.banking.web.commandside.transactions.CreateMoneyTransferRequest;
import net.chrisrichardson.eventstore.javaexamples.banking.web.commandside.transactions.CreateMoneyTransferResponse;
import net.chrisrichardson.eventstore.javaexamples.banking.web.queryside.accounts.GetAccountResponse;
import net.chrisrichardson.eventstore.javaexamples.banking.web.commandside.accounts.CreateAccountRequest;
import net.chrisrichardson.eventstore.javaexamples.banking.web.commandside.accounts.CreateAccountResponse;
import net.chrisrichardson.eventstorestore.javaexamples.testutil.Producer;
import net.chrisrichardson.eventstorestore.javaexamples.testutil.Verifier;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -13,16 +16,15 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.IntegrationTest;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.web.client.RestTemplate;
import rx.Observable;
import java.math.BigDecimal;
import net.chrisrichardson.eventstorestore.javaexamples.testutil.Producer;
import net.chrisrichardson.eventstorestore.javaexamples.testutil.Verifier;
import rx.Observable;
import static net.chrisrichardson.eventstorestore.javaexamples.testutil.TestUtil.eventually;
@RunWith(SpringJUnit4ClassRunner.class)
@@ -51,10 +53,21 @@ public class BankingWebIntegrationTest {
BigDecimal finalFromAccountBalance = initialFromAccountBalance.subtract(amountToTransfer);
BigDecimal finalToAccountBalance = initialToAccountBalance.add(amountToTransfer);
final CreateAccountResponse fromAccount = restTemplate.postForEntity(baseUrl("/accounts"), new CreateAccountRequest("00000000-00000000", "My Account", initialFromAccountBalance), CreateAccountResponse.class).getBody();
final CreateAccountResponse fromAccount = BasicAuthUtils.doRestTemplateRequest(restTemplate,
baseUrl("/accounts"),
HttpMethod.POST,
CreateAccountResponse.class,
new CreateAccountRequest("00000000-00000000", "My 1 Account", initialFromAccountBalance)
);
final String fromAccountId = fromAccount.getAccountId();
CreateAccountResponse toAccount = restTemplate.postForEntity(baseUrl("/accounts"), new CreateAccountRequest("00000000-00000000", "My Account", initialToAccountBalance), CreateAccountResponse.class).getBody();
CreateAccountResponse toAccount = BasicAuthUtils.doRestTemplateRequest(restTemplate,
baseUrl("/accounts"),
HttpMethod.POST,
CreateAccountResponse.class,
new CreateAccountRequest("00000000-00000000", "My 2 Account", initialToAccountBalance)
);
String toAccountId = toAccount.getAccountId();
Assert.assertNotNull(fromAccountId);
@@ -64,8 +77,12 @@ public class BankingWebIntegrationTest {
assertAccountBalance(toAccountId, initialToAccountBalance);
final CreateMoneyTransferResponse moneyTransfer = restTemplate.postForEntity(baseUrl("/transfers"),
new CreateMoneyTransferRequest(fromAccountId, toAccountId, amountToTransfer), CreateMoneyTransferResponse.class).getBody();
final CreateMoneyTransferResponse moneyTransfer = BasicAuthUtils.doRestTemplateRequest(restTemplate,
baseUrl("/transfers"),
HttpMethod.POST,
CreateMoneyTransferResponse.class,
new CreateMoneyTransferRequest(fromAccountId, toAccountId, amountToTransfer)
);
assertAccountBalance(fromAccountId, finalFromAccountBalance);
assertAccountBalance(toAccountId, finalToAccountBalance);
@@ -95,7 +112,10 @@ public class BankingWebIntegrationTest {
new Producer<GetAccountResponse>() {
@Override
public Observable<GetAccountResponse> produce() {
return Observable.just(restTemplate.getForEntity(baseUrl("/accounts/" + fromAccountId), GetAccountResponse.class).getBody());
return Observable.just(BasicAuthUtils.doRestTemplateRequest(restTemplate,
baseUrl("/accounts/" + fromAccountId),
HttpMethod.GET,
GetAccountResponse.class));
}
},
new Verifier<GetAccountResponse>() {
@@ -112,7 +132,10 @@ public class BankingWebIntegrationTest {
new Producer<CustomerResponse>() {
@Override
public Observable<CustomerResponse> produce() {
return Observable.just(restTemplate.getForEntity(baseUrl("/customers/" + customerId), CustomerResponse.class).getBody());
return Observable.just(BasicAuthUtils.doRestTemplateRequest(restTemplate,
baseUrl("/customers/" + customerId),
HttpMethod.GET,
CustomerResponse.class));
}
},
new Verifier<CustomerResponse>() {
@@ -141,4 +164,6 @@ public class BankingWebIntegrationTest {
private ToAccountInfo generateToAccountInfo() {
return new ToAccountInfo("11111111-11111111", "New Account", "John Doe");
}
}