Add WebFlux
Fixes gh-4128
This commit is contained in:
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright 2002-2017 the original author or authors.
|
||||
* *
|
||||
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* * you may not use this file except in compliance with the License.
|
||||
* * You may obtain a copy of the License at
|
||||
* *
|
||||
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||
* *
|
||||
* * Unless required by applicable law or agreed to in writing, software
|
||||
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* * See the License for the specific language governing permissions and
|
||||
* * limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.security.authentication;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public class MapUserDetailsRepository implements UserDetailsRepository {
|
||||
private final Map<String,UserDetails> users;
|
||||
|
||||
public MapUserDetailsRepository(Collection<UserDetails> users) {
|
||||
Assert.notEmpty(users, "users cannot be null or empty");
|
||||
this.users = users.stream().collect(Collectors.toMap( u -> getKey(u.getName()), Function.identity()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<UserDetails> findByUsername(String username) {
|
||||
String key = getKey(username);
|
||||
UserDetails result = users.get(key);
|
||||
return result == null ? Mono.empty() : Mono.just(User.withUserDetails(result).build());
|
||||
}
|
||||
|
||||
private String getKey(String username) {
|
||||
return username.toLowerCase();
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.authentication;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public interface ReactiveAuthenticationManager {
|
||||
|
||||
Mono<Authentication> authenticate(Authentication authentication);
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.authentication;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.util.Assert;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
|
||||
/**
|
||||
* Adapts an AuthenticationManager to the reactive APIs. This is somewhat necessary because many of the ways that
|
||||
* credentials are stored (i.e. JDBC, LDAP, etc) do not have reactive implementations. What's more is it is generally
|
||||
* considered best practice to store passwords in a hash that is intentionally slow which would block ever request
|
||||
* from coming in unless it was put on another thread.
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public class ReactiveAuthenticationManagerAdapter implements ReactiveAuthenticationManager {
|
||||
private final AuthenticationManager authenticationManager;
|
||||
|
||||
public ReactiveAuthenticationManagerAdapter(AuthenticationManager authenticationManager) {
|
||||
Assert.notNull(authenticationManager, "authenticationManager cannot be null");
|
||||
this.authenticationManager = authenticationManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Authentication> authenticate(Authentication token) {
|
||||
return Mono.just(token)
|
||||
.publishOn(Schedulers.elastic())
|
||||
.flatMap( t -> {
|
||||
try {
|
||||
return Mono.just(authenticationManager.authenticate(t));
|
||||
} catch(Throwable error) {
|
||||
return Mono.error(error);
|
||||
}
|
||||
})
|
||||
.filter( a -> a.isAuthenticated());
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package org.springframework.security.authentication;
|
||||
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public interface UserDetailsRepository {
|
||||
|
||||
Mono<UserDetails> findByUsername(String username);
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright 2002-2017 the original author or authors.
|
||||
* *
|
||||
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* * you may not use this file except in compliance with the License.
|
||||
* * You may obtain a copy of the License at
|
||||
* *
|
||||
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||
* *
|
||||
* * Unless required by applicable law or agreed to in writing, software
|
||||
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* * See the License for the specific language governing permissions and
|
||||
* * limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.security.authentication;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public class UserDetailsRepositoryAuthenticationManager implements ReactiveAuthenticationManager {
|
||||
private final UserDetailsRepository repository;
|
||||
|
||||
public UserDetailsRepositoryAuthenticationManager(UserDetailsRepository userDetailsRepository) {
|
||||
Assert.notNull(userDetailsRepository, "userDetailsRepository cannot be null");
|
||||
this.repository = userDetailsRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Authentication> authenticate(Authentication authentication) {
|
||||
final String username = authentication.getName();
|
||||
return repository
|
||||
.findByUsername(username)
|
||||
.filter( u -> u.getPassword().equals(authentication.getCredentials()))
|
||||
.switchIfEmpty( Mono.error(new BadCredentialsException("Invalid Credentials")) )
|
||||
.map( u -> new UsernamePasswordAuthenticationToken(u, u.getPassword(), u.getAuthorities()) );
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright 2002-2017 the original author or authors.
|
||||
* *
|
||||
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* * you may not use this file except in compliance with the License.
|
||||
* * You may obtain a copy of the License at
|
||||
* *
|
||||
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||
* *
|
||||
* * Unless required by applicable law or agreed to in writing, software
|
||||
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* * See the License for the specific language governing permissions and
|
||||
* * limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.security.authorization;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public class AuthenticatedAuthorizationManager<T> implements ReactiveAuthorizationManager<T> {
|
||||
|
||||
@Override
|
||||
public Mono<AuthorizationDecision> check(Mono<Authentication> authentication, T object) {
|
||||
return authentication
|
||||
.map(a -> new AuthorizationDecision(a.isAuthenticated()))
|
||||
.defaultIfEmpty(new AuthorizationDecision(false));
|
||||
}
|
||||
|
||||
public static <T> AuthenticatedAuthorizationManager<T> authenticated() {
|
||||
return new AuthenticatedAuthorizationManager<>();
|
||||
}
|
||||
|
||||
private AuthenticatedAuthorizationManager() {}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright 2002-2017 the original author or authors.
|
||||
* *
|
||||
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* * you may not use this file except in compliance with the License.
|
||||
* * You may obtain a copy of the License at
|
||||
* *
|
||||
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||
* *
|
||||
* * Unless required by applicable law or agreed to in writing, software
|
||||
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* * See the License for the specific language governing permissions and
|
||||
* * limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.security.authorization;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.util.Assert;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public class AuthorityAuthorizationManager<T> implements ReactiveAuthorizationManager<T> {
|
||||
private final String authority;
|
||||
|
||||
private AuthorityAuthorizationManager(String authority) {
|
||||
this.authority = authority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<AuthorizationDecision> check(Mono<Authentication> authentication, T object) {
|
||||
return authentication
|
||||
.filter(a -> a.isAuthenticated())
|
||||
.flatMapIterable( a -> a.getAuthorities())
|
||||
.map( g-> g.getAuthority())
|
||||
.hasElement(this.authority)
|
||||
.map( hasAuthority -> new AuthorizationDecision(hasAuthority))
|
||||
.defaultIfEmpty(new AuthorizationDecision(false));
|
||||
}
|
||||
|
||||
public static <T> AuthorityAuthorizationManager<T> hasAuthority(String authority) {
|
||||
Assert.notNull(authority, "authority cannot be null");
|
||||
return new AuthorityAuthorizationManager<>(authority);
|
||||
}
|
||||
|
||||
public static <T> AuthorityAuthorizationManager<T> hasRole(String role) {
|
||||
Assert.notNull(role, "role cannot be null");
|
||||
return hasAuthority("ROLE_" + role);
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright 2002-2017 the original author or authors.
|
||||
* *
|
||||
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* * you may not use this file except in compliance with the License.
|
||||
* * You may obtain a copy of the License at
|
||||
* *
|
||||
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||
* *
|
||||
* * Unless required by applicable law or agreed to in writing, software
|
||||
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* * See the License for the specific language governing permissions and
|
||||
* * limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.security.authorization;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public class AuthorizationDecision {
|
||||
private final boolean granted;
|
||||
|
||||
public AuthorizationDecision(boolean granted) {
|
||||
this.granted = granted;
|
||||
}
|
||||
|
||||
public boolean isGranted() {
|
||||
return granted;
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright 2002-2017 the original author or authors.
|
||||
* *
|
||||
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* * you may not use this file except in compliance with the License.
|
||||
* * You may obtain a copy of the License at
|
||||
* *
|
||||
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||
* *
|
||||
* * Unless required by applicable law or agreed to in writing, software
|
||||
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* * See the License for the specific language governing permissions and
|
||||
* * limitations under the License.
|
||||
*
|
||||
*/
|
||||
package org.springframework.security.authorization;
|
||||
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
public interface ReactiveAuthorizationManager<T> {
|
||||
Mono<AuthorizationDecision> check(Mono<Authentication> authentication, T object);
|
||||
|
||||
default Mono<Void> verify(Mono<Authentication> authentication, T object) {
|
||||
return check(authentication, object)
|
||||
.filter( d -> d.isGranted())
|
||||
.switchIfEmpty( Mono.error(new AccessDeniedException("Access Denied")) )
|
||||
.flatMap( d -> Mono.empty() );
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.authentication;
|
||||
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public class MapUserDetailsRepositoryTests {
|
||||
private static final UserDetails USER_DETAILS = User.withUsername("user")
|
||||
.password("password")
|
||||
.roles("USER")
|
||||
.build();
|
||||
|
||||
private MapUserDetailsRepository users = new MapUserDetailsRepository(Arrays.asList(USER_DETAILS));
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructorNullUsers() {
|
||||
Collection<UserDetails> users = null;
|
||||
new MapUserDetailsRepository(users);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructorEmptyUsers() {
|
||||
Collection<UserDetails> users = Collections.emptyList();
|
||||
new MapUserDetailsRepository(users);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByUsernameWhenFoundThenReturns() {
|
||||
assertThat((users.findByUsername(USER_DETAILS.getUsername()).block())).isEqualTo(USER_DETAILS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByUsernameWhenDifferentCaseThenReturns() {
|
||||
assertThat((users.findByUsername("uSeR").block())).isEqualTo(USER_DETAILS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByUsernameWhenClearCredentialsThenFindByUsernameStillHasCredentials() {
|
||||
User foundUser = users.findByUsername(USER_DETAILS.getUsername()).cast(User.class).block();
|
||||
assertThat(foundUser.getPassword()).isNotEmpty();
|
||||
foundUser.eraseCredentials();
|
||||
assertThat(foundUser.getPassword()).isNull();
|
||||
|
||||
foundUser = users.findByUsername(USER_DETAILS.getUsername()).cast(User.class).block();
|
||||
assertThat(foundUser.getPassword()).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByUsernameWhenNotFoundThenEmpty() {
|
||||
assertThat((users.findByUsername("notfound"))).isEqualTo(Mono.empty());
|
||||
}
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright 2002-2017 the original author or authors.
|
||||
* *
|
||||
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* * you may not use this file except in compliance with the License.
|
||||
* * You may obtain a copy of the License at
|
||||
* *
|
||||
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||
* *
|
||||
* * Unless required by applicable law or agreed to in writing, software
|
||||
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* * See the License for the specific language governing permissions and
|
||||
* * limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.security.authentication;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ReactiveAuthenticationManagerAdapterTests {
|
||||
@Mock
|
||||
AuthenticationManager delegate;
|
||||
@Mock
|
||||
Authentication authentication;
|
||||
|
||||
ReactiveAuthenticationManagerAdapter manager;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
manager = new ReactiveAuthenticationManagerAdapter(delegate);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructorNullAuthenticationManager() {
|
||||
new ReactiveAuthenticationManagerAdapter(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenSuccessThenSucces() {
|
||||
when(delegate.authenticate(any())).thenReturn(authentication);
|
||||
when(authentication.isAuthenticated()).thenReturn(true);
|
||||
|
||||
Authentication result = manager.authenticate(authentication).block();
|
||||
|
||||
assertThat(result).isEqualTo(authentication);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenReturnNotAuthenticatedThenError() {
|
||||
when(delegate.authenticate(any())).thenReturn(authentication);
|
||||
|
||||
Authentication result = manager.authenticate(authentication).block();
|
||||
|
||||
assertThat(result).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenBadCredentialsThenError() {
|
||||
when(delegate.authenticate(any())).thenThrow(new BadCredentialsException("Failed"));
|
||||
when(authentication.isAuthenticated()).thenReturn(true);
|
||||
|
||||
Mono<Authentication> result = manager.authenticate(authentication);
|
||||
|
||||
StepVerifier.create(result)
|
||||
.expectError(BadCredentialsException.class)
|
||||
.verify();
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.security.authentication;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class UserDetailsRepositoryAuthenticationManagerTests {
|
||||
@Mock
|
||||
UserDetailsRepository repository;
|
||||
UserDetailsRepositoryAuthenticationManager manager;
|
||||
String username;
|
||||
String password;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
manager = new UserDetailsRepositoryAuthenticationManager(repository);
|
||||
username = "user";
|
||||
password = "pass";
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void constructorNullUserDetailsRepository() {
|
||||
UserDetailsRepository udr = null;
|
||||
new UserDetailsRepositoryAuthenticationManager(udr);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenUserNotFoundThenBadCredentials() {
|
||||
when(repository.findByUsername(username)).thenReturn(Mono.empty());
|
||||
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
|
||||
Mono<Authentication> authentication = manager.authenticate(token);
|
||||
|
||||
StepVerifier
|
||||
.create(authentication)
|
||||
.expectError(BadCredentialsException.class)
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenPasswordNotEqualThenBadCredentials() {
|
||||
User user = new User(username, password, AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
when(repository.findByUsername(user.getUsername())).thenReturn(Mono.just(user));
|
||||
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password + "INVALID");
|
||||
Mono<Authentication> authentication = manager.authenticate(token);
|
||||
|
||||
StepVerifier
|
||||
.create(authentication)
|
||||
.expectError(BadCredentialsException.class)
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void authenticateWhenSuccessThenSuccess() {
|
||||
User user = new User(username, password, AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
when(repository.findByUsername(user.getUsername())).thenReturn(Mono.just(user));
|
||||
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
|
||||
Authentication authentication = manager.authenticate(token).block();
|
||||
|
||||
assertThat(authentication).isEqualTo(authentication);
|
||||
}
|
||||
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright 2002-2017 the original author or authors.
|
||||
* *
|
||||
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* * you may not use this file except in compliance with the License.
|
||||
* * You may obtain a copy of the License at
|
||||
* *
|
||||
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||
* *
|
||||
* * Unless required by applicable law or agreed to in writing, software
|
||||
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* * See the License for the specific language governing permissions and
|
||||
* * limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.security.authorization;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AuthenticatedAuthorizationManagerTests {
|
||||
@Mock
|
||||
Authentication authentication;
|
||||
|
||||
AuthenticatedAuthorizationManager<Object> manager = AuthenticatedAuthorizationManager.authenticated();
|
||||
|
||||
@Test
|
||||
public void checkWhenAuthenticatedThenReturnTrue() {
|
||||
when(authentication.isAuthenticated()).thenReturn(true);
|
||||
|
||||
boolean granted = manager.check(Mono.just(authentication), null).block().isGranted();
|
||||
|
||||
assertThat(granted).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkWhenNotAuthenticatedThenReturnFalse() {
|
||||
boolean granted = manager.check(Mono.just(authentication), null).block().isGranted();
|
||||
|
||||
assertThat(granted).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkWhenEmptyThenReturnFalse() {
|
||||
boolean granted = manager.check(Mono.empty(), null).block().isGranted();
|
||||
|
||||
assertThat(granted).isFalse();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void checkWhenErrorThenError() {
|
||||
Mono<AuthorizationDecision> result = manager.check(Mono.error(new RuntimeException("ooops")), null);
|
||||
|
||||
StepVerifier
|
||||
.create(result)
|
||||
.expectError()
|
||||
.verify();
|
||||
}
|
||||
}
|
||||
+133
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright 2002-2017 the original author or authors.
|
||||
* *
|
||||
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* * you may not use this file except in compliance with the License.
|
||||
* * You may obtain a copy of the License at
|
||||
* *
|
||||
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||
* *
|
||||
* * Unless required by applicable law or agreed to in writing, software
|
||||
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* * See the License for the specific language governing permissions and
|
||||
* * limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.springframework.security.authorization;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.springframework.security.core.authority.AuthorityUtils.createAuthorityList;
|
||||
|
||||
/**
|
||||
* @author Rob Winch
|
||||
* @since 5.0
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AuthorityAuthorizationManagerTests {
|
||||
@Mock
|
||||
Authentication authentication;
|
||||
|
||||
AuthorityAuthorizationManager<Object> manager = AuthorityAuthorizationManager.hasAuthority("ADMIN");
|
||||
|
||||
@Test
|
||||
public void checkWhenHasAuthorityAndNotAuthenticatedThenReturnFalse() {
|
||||
boolean granted = manager.check(Mono.just(authentication), null).block().isGranted();
|
||||
|
||||
assertThat(granted).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkWhenHasAuthorityAndEmptyThenReturnFalse() {
|
||||
boolean granted = manager.check(Mono.empty(), null).block().isGranted();
|
||||
|
||||
assertThat(granted).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkWhenHasAuthorityAndErrorThenError() {
|
||||
Mono<AuthorizationDecision> result = manager.check(Mono.error(new RuntimeException("ooops")), null);
|
||||
|
||||
StepVerifier
|
||||
.create(result)
|
||||
.expectError()
|
||||
.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkWhenHasAuthorityAndAuthenticatedAndNoAuthoritiesThenReturnFalse() {
|
||||
when(authentication.isAuthenticated()).thenReturn(true);
|
||||
when(authentication.getAuthorities()).thenReturn(Collections.emptyList());
|
||||
|
||||
boolean granted = manager.check(Mono.just(authentication), null).block().isGranted();
|
||||
|
||||
assertThat(granted).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkWhenHasAuthorityAndAuthenticatedAndWrongAuthoritiesThenReturnFalse() {
|
||||
authentication = new TestingAuthenticationToken("rob", "secret", "ROLE_ADMIN");
|
||||
|
||||
boolean granted = manager.check(Mono.just(authentication), null).block().isGranted();
|
||||
|
||||
assertThat(granted).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkWhenHasAuthorityAndAuthorizedThenReturnTrue() {
|
||||
authentication = new TestingAuthenticationToken("rob", "secret", "ADMIN");
|
||||
|
||||
boolean granted = manager.check(Mono.just(authentication), null).block().isGranted();
|
||||
|
||||
assertThat(granted).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkWhenHasRoleAndAuthorizedThenReturnTrue() {
|
||||
manager = AuthorityAuthorizationManager.hasRole("ADMIN");
|
||||
authentication = new TestingAuthenticationToken("rob", "secret", "ROLE_ADMIN");
|
||||
|
||||
boolean granted = manager.check(Mono.just(authentication), null).block().isGranted();
|
||||
|
||||
assertThat(granted).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkWhenHasRoleAndNotAuthorizedThenReturnTrue() {
|
||||
manager = AuthorityAuthorizationManager.hasRole("ADMIN");
|
||||
authentication = new TestingAuthenticationToken("rob", "secret", "ADMIN");
|
||||
|
||||
boolean granted = manager.check(Mono.just(authentication), null).block().isGranted();
|
||||
|
||||
assertThat(granted).isFalse();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void hasRoleWhenNullThenException() {
|
||||
String role = null;
|
||||
AuthorityAuthorizationManager.hasRole(role);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void hasAuthorityWhenNullThenException() {
|
||||
String authority = null;
|
||||
AuthorityAuthorizationManager.hasAuthority(authority);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user