Use java.util.Function instead of Converter

Fixes gh-4323
This commit is contained in:
Joe Grandja 2017-06-01 16:04:24 -04:00
parent ac6a86fb5f
commit 6c0ecea494
14 changed files with 51 additions and 52 deletions

View File

@ -15,7 +15,6 @@
*/
package org.springframework.security.config.annotation.web.configurers.oauth2.client;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
@ -34,6 +33,7 @@ import org.springframework.util.Assert;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
/**
* @author Joe Grandja
@ -43,7 +43,7 @@ final class AuthorizationCodeAuthenticationFilterConfigurer<H extends HttpSecuri
private AuthorizationGrantTokenExchanger<AuthorizationCodeAuthenticationToken> authorizationCodeTokenExchanger;
private OAuth2UserService userInfoService;
private Map<URI, Converter<ClientHttpResponse, ? extends OAuth2User>> userInfoTypeConverters = new HashMap<>();
private Map<URI, Function<ClientHttpResponse, ? extends OAuth2User>> userInfoTypeConverters = new HashMap<>();
AuthorizationCodeAuthenticationFilterConfigurer() {
@ -71,7 +71,7 @@ final class AuthorizationCodeAuthenticationFilterConfigurer<H extends HttpSecuri
return this;
}
AuthorizationCodeAuthenticationFilterConfigurer<H> userInfoTypeConverter(Converter<ClientHttpResponse, ? extends OAuth2User> userInfoConverter, URI userInfoUri) {
AuthorizationCodeAuthenticationFilterConfigurer<H> userInfoTypeConverter(Function<ClientHttpResponse, ? extends OAuth2User> userInfoConverter, URI userInfoUri) {
Assert.notNull(userInfoConverter, "userInfoConverter cannot be null");
Assert.notNull(userInfoUri, "userInfoUri cannot be null");
this.userInfoTypeConverters.put(userInfoUri, userInfoConverter);

View File

@ -16,7 +16,6 @@
package org.springframework.security.config.annotation.web.configurers.oauth2.client;
import org.springframework.context.ApplicationContext;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
@ -36,6 +35,7 @@ import org.springframework.util.CollectionUtils;
import java.net.URI;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
@ -95,7 +95,7 @@ public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>> exten
return this.and();
}
public OAuth2LoginConfigurer<B> userInfoTypeConverter(Converter<ClientHttpResponse, ? extends OAuth2User> userInfoConverter, URI userInfoUri) {
public OAuth2LoginConfigurer<B> userInfoTypeConverter(Function<ClientHttpResponse, ? extends OAuth2User> userInfoConverter, URI userInfoUri) {
Assert.notNull(userInfoConverter, "userInfoConverter cannot be null");
Assert.notNull(userInfoUri, "userInfoUri cannot be null");
OAuth2LoginConfigurer.this.authorizationCodeAuthenticationFilterConfigurer.userInfoTypeConverter(userInfoConverter, userInfoUri);

View File

@ -123,7 +123,7 @@ public class AuthorizationCodeAuthenticationProcessingFilter extends AbstractAut
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
ErrorResponseAttributes authorizationError = this.errorResponseConverter.convert(request);
ErrorResponseAttributes authorizationError = this.errorResponseConverter.apply(request);
if (authorizationError != null) {
OAuth2Error oauth2Error = new OAuth2Error(authorizationError.getErrorCode(),
authorizationError.getDescription(), authorizationError.getUri());
@ -144,7 +144,7 @@ public class AuthorizationCodeAuthenticationProcessingFilter extends AbstractAut
}
AuthorizationCodeAuthorizationResponseAttributes authorizationCodeResponseAttributes =
this.authorizationCodeResponseConverter.convert(request);
this.authorizationCodeResponseConverter.apply(request);
AuthorizationCodeAuthenticationToken authRequest = new AuthorizationCodeAuthenticationToken(
authorizationCodeResponseAttributes.getCode(), clientRegistration);

View File

@ -15,7 +15,6 @@
*/
package org.springframework.security.oauth2.client.user.converter;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
@ -23,9 +22,10 @@ import org.springframework.security.oauth2.core.user.OAuth2User;
import java.io.IOException;
import java.util.Map;
import java.util.function.Function;
/**
* Base implementation of a {@link Converter} that converts a {@link ClientHttpResponse}
* Base implementation of a <code>Function</code> that converts a {@link ClientHttpResponse}
* to a specific type of {@link OAuth2User}.
*
* @author Joe Grandja
@ -33,14 +33,14 @@ import java.util.Map;
* @see OAuth2User
* @see ClientHttpResponse
*/
public abstract class AbstractOAuth2UserConverter<T extends OAuth2User> implements Converter<ClientHttpResponse, T> {
public abstract class AbstractOAuth2UserConverter<R extends OAuth2User> implements Function<ClientHttpResponse, R> {
private final HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
protected AbstractOAuth2UserConverter() {
}
@Override
public final T convert(ClientHttpResponse clientHttpResponse) {
public final R apply(ClientHttpResponse clientHttpResponse) {
Map<String, Object> userAttributes;
try {
@ -49,9 +49,9 @@ public abstract class AbstractOAuth2UserConverter<T extends OAuth2User> implemen
throw new IllegalArgumentException("An error occurred reading the UserInfo response: " + ex.getMessage(), ex);
}
return this.convert(userAttributes);
return this.apply(userAttributes);
}
protected abstract T convert(Map<String, Object> userAttributes);
protected abstract R apply(Map<String, Object> userAttributes);
}

View File

@ -15,16 +15,17 @@
*/
package org.springframework.security.oauth2.client.user.converter;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.util.Assert;
import java.io.IOException;
import java.util.function.Function;
/**
* An implementation of a {@link Converter} that converts a {@link ClientHttpResponse}
* A <code>Function</code> that converts a {@link ClientHttpResponse}
* to a custom type of {@link OAuth2User}, as supplied via the constructor.
*
* @author Joe Grandja
@ -32,20 +33,21 @@ import java.io.IOException;
* @see OAuth2User
* @see ClientHttpResponse
*/
public final class CustomOAuth2UserConverter<T extends OAuth2User> implements Converter<ClientHttpResponse, T> {
public final class CustomOAuth2UserConverter<R extends OAuth2User> implements Function<ClientHttpResponse, R> {
private final HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
private final Class<T> customType;
private final Class<R> customType;
public CustomOAuth2UserConverter(Class<T> customType) {
public CustomOAuth2UserConverter(Class<R> customType) {
Assert.notNull(customType, "customType cannot be null");
this.customType = customType;
}
@Override
public T convert(ClientHttpResponse clientHttpResponse) {
T user;
public R apply(ClientHttpResponse clientHttpResponse) {
R user;
try {
user = (T) this.jackson2HttpMessageConverter.read(this.customType, clientHttpResponse);
user = (R) this.jackson2HttpMessageConverter.read(this.customType, clientHttpResponse);
} catch (IOException ex) {
throw new IllegalArgumentException("An error occurred reading the UserInfo response: " + ex.getMessage(), ex);
}

View File

@ -40,7 +40,7 @@ public final class OAuth2UserConverter extends AbstractOAuth2UserConverter<OAuth
}
@Override
protected OAuth2User convert(Map<String, Object> userAttributes) {
protected OAuth2User apply(Map<String, Object> userAttributes) {
return new DefaultOAuth2User(userAttributes, this.nameAttributeKey);
}
}

View File

@ -33,7 +33,7 @@ import java.util.Map;
public final class UserInfoConverter extends AbstractOAuth2UserConverter<UserInfo> {
@Override
protected UserInfo convert(Map<String, Object> userAttributes) {
protected UserInfo apply(Map<String, Object> userAttributes) {
return new DefaultUserInfo(userAttributes);
}
}

View File

@ -14,7 +14,6 @@
* limitations under the License.
*/
/**
* {@link org.springframework.core.convert.converter.Converter} implementations
* for {@link org.springframework.security.oauth2.core.user.OAuth2User}.
* Support classes for converting to {@link org.springframework.security.oauth2.core.user.OAuth2User}.
*/
package org.springframework.security.oauth2.client.user.converter;

View File

@ -22,7 +22,6 @@ import com.nimbusds.oauth2.sdk.http.HTTPResponse;
import com.nimbusds.oauth2.sdk.token.BearerAccessToken;
import com.nimbusds.openid.connect.sdk.UserInfoErrorResponse;
import com.nimbusds.openid.connect.sdk.UserInfoRequest;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.security.authentication.AuthenticationServiceException;
@ -40,13 +39,14 @@ import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
/**
* An implementation of an {@link OAuth2UserService} that uses the <b>Nimbus OAuth 2.0 SDK</b> internally.
*
* <p>
* This implementation uses a <code>Map</code> of <code>Converter</code>'s <i>keyed</i> by <code>URI</code>.
* The <code>URI</code> represents the <i>UserInfo Endpoint</i> address and the mapped <code>Converter</code>
* This implementation uses a <code>Map</code> of converter's <i>keyed</i> by <code>URI</code>.
* The <code>URI</code> represents the <i>UserInfo Endpoint</i> address and the mapped <code>Function</code>
* is capable of converting the <i>UserInfo Response</i> to either an
* {@link OAuth2User} (for a standard <i>OAuth 2.0 Provider</i>) or
* {@link UserInfo} (for an <i>OpenID Connect 1.0 Provider</i>).
@ -57,14 +57,13 @@ import java.util.Map;
* @see AuthenticatedPrincipal
* @see OAuth2User
* @see UserInfo
* @see Converter
* @see <a target="_blank" href="https://connect2id.com/products/nimbus-oauth-openid-connect-sdk">Nimbus OAuth 2.0 SDK</a>
*/
public class NimbusOAuth2UserService implements OAuth2UserService {
private static final String INVALID_USER_INFO_RESPONSE_ERROR_CODE = "invalid_user_info_response";
private final Map<URI, Converter<ClientHttpResponse, ? extends OAuth2User>> userInfoTypeConverters;
private final Map<URI, Function<ClientHttpResponse, ? extends OAuth2User>> userInfoTypeConverters;
public NimbusOAuth2UserService(Map<URI, Converter<ClientHttpResponse, ? extends OAuth2User>> userInfoTypeConverters) {
public NimbusOAuth2UserService(Map<URI, Function<ClientHttpResponse, ? extends OAuth2User>> userInfoTypeConverters) {
Assert.notEmpty(userInfoTypeConverters, "userInfoTypeConverters cannot be empty");
this.userInfoTypeConverters = new HashMap<>(userInfoTypeConverters);
}
@ -84,7 +83,7 @@ public class NimbusOAuth2UserService implements OAuth2UserService {
clientRegistration.getProviderDetails().getUserInfoUri(), ex);
}
Converter<ClientHttpResponse, ? extends OAuth2User> userInfoConverter = this.userInfoTypeConverters.get(userInfoUri);
Function<ClientHttpResponse, ? extends OAuth2User> userInfoConverter = this.userInfoTypeConverters.get(userInfoUri);
if (userInfoConverter == null) {
throw new IllegalArgumentException("There is no available User Info converter for " + userInfoUri.toString());
}
@ -118,7 +117,7 @@ public class NimbusOAuth2UserService implements OAuth2UserService {
throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
}
user = userInfoConverter.convert(new NimbusClientHttpResponse(httpResponse));
user = userInfoConverter.apply(new NimbusClientHttpResponse(httpResponse));
} catch (ParseException ex) {
// This error occurs if the User Info Response is not well-formed or invalid

View File

@ -15,15 +15,15 @@
*/
package org.springframework.security.oauth2.client.web.converter;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.oauth2.core.endpoint.AuthorizationCodeAuthorizationResponseAttributes;
import org.springframework.security.oauth2.core.endpoint.OAuth2Parameter;
import org.springframework.util.Assert;
import javax.servlet.http.HttpServletRequest;
import java.util.function.Function;
/**
* An implementation of a {@link Converter} that converts an <i>OAuth 2.0 Authorization Code Grant Response</i>
* A <code>Function</code> that converts an <i>OAuth 2.0 Authorization Code Grant Response</i>
* (in the form of a {@link HttpServletRequest}) to a {@link AuthorizationCodeAuthorizationResponseAttributes}.
*
* @author Joe Grandja
@ -31,10 +31,10 @@ import javax.servlet.http.HttpServletRequest;
* @see AuthorizationCodeAuthorizationResponseAttributes
* @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-4.1.2">Section 4.1.2 Authorization Code Grant Response</a>
*/
public final class AuthorizationCodeAuthorizationResponseAttributesConverter implements Converter<HttpServletRequest, AuthorizationCodeAuthorizationResponseAttributes> {
public final class AuthorizationCodeAuthorizationResponseAttributesConverter implements Function<HttpServletRequest, AuthorizationCodeAuthorizationResponseAttributes> {
@Override
public AuthorizationCodeAuthorizationResponseAttributes convert(HttpServletRequest request) {
public AuthorizationCodeAuthorizationResponseAttributes apply(HttpServletRequest request) {
AuthorizationCodeAuthorizationResponseAttributes response;
String code = request.getParameter(OAuth2Parameter.CODE);

View File

@ -15,25 +15,25 @@
*/
package org.springframework.security.oauth2.client.web.converter;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.oauth2.core.endpoint.ErrorResponseAttributes;
import org.springframework.security.oauth2.core.endpoint.OAuth2Parameter;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.function.Function;
/**
* An implementation of a {@link Converter} that converts an <i>OAuth 2.0 Error Response</i>
* A <code>Function</code> that converts an <i>OAuth 2.0 Error Response</i>
* (in the form of a {@link HttpServletRequest}) to a {@link ErrorResponseAttributes}.
*
* @author Joe Grandja
* @since 5.0
* @see ErrorResponseAttributes
*/
public final class ErrorResponseAttributesConverter implements Converter<HttpServletRequest, ErrorResponseAttributes> {
public final class ErrorResponseAttributesConverter implements Function<HttpServletRequest, ErrorResponseAttributes> {
@Override
public ErrorResponseAttributes convert(HttpServletRequest request) {
public ErrorResponseAttributes apply(HttpServletRequest request) {
ErrorResponseAttributes response;
String errorCode = request.getParameter(OAuth2Parameter.ERROR);

View File

@ -14,7 +14,6 @@
* limitations under the License.
*/
/**
* {@link org.springframework.core.convert.converter.Converter} implementations
* for <i>OAuth 2.0 Protocol Endpoint Messages</i>.
* Support classes for converting <i>OAuth 2.0 Protocol Endpoint Messages</i>.
*/
package org.springframework.security.oauth2.client.web.converter;

View File

@ -410,9 +410,9 @@ NOTE: Non-standard scopes may be defined by a standard _OAuth 2.0 Provider_. Ple
- *authorization-uri* - the URI used by the client to redirect the end-user's user-agent to the _Authorization Server_ in order to obtain authorization from the end-user (the _Resource Owner_).
- *token-uri* - the URI used by the client when exchanging an _Authorization Grant_ (for example, Authorization Code) for an _Access Token_ at the _Authorization Server_.
- *user-info-uri* - the URI used by the client to access the protected resource *UserInfo Endpoint*, in order to obtain attributes of the end-user.
- *user-info-converter* - the `Converter` implementation class used to convert the *UserInfo Response* to a `UserInfo` (_OpenID Connect 1.0 Provider_) or `OAuth2User` instance (_Standard OAuth 2.0 Provider_).
- *user-info-converter* - the `java.util.function.Function` implementation class used to convert the *UserInfo Response* to a `UserInfo` (_OpenID Connect 1.0 Provider_) or `OAuth2User` instance (_Standard OAuth 2.0 Provider_).
TIP: The `Converter` implementation class for an _OpenID Connect 1.0 Provider_ is *org.springframework.security.oauth2.client.user.converter.UserInfoConverter*
TIP: The `java.util.function.Function` implementation class for an _OpenID Connect 1.0 Provider_ is *org.springframework.security.oauth2.client.user.converter.UserInfoConverter*
and for a standard _OAuth 2.0 Provider_ it's *org.springframework.security.oauth2.client.user.converter.OAuth2UserConverter*.
- *user-info-name-attribute-key* - the _key_ used to retrieve the *Name* of the end-user from the `Map` of available attributes in `UserInfo` or `OAuth2User`.

View File

@ -23,7 +23,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.env.Environment;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@ -39,6 +38,7 @@ import org.springframework.util.ClassUtils;
import java.lang.reflect.Constructor;
import java.net.URI;
import java.util.Set;
import java.util.function.Function;
import static org.springframework.boot.autoconfigure.security.oauth2.client.ClientRegistrationAutoConfiguration.CLIENT_PROPERTY_PREFIX;
import static org.springframework.boot.autoconfigure.security.oauth2.client.ClientRegistrationAutoConfiguration.resolveClientPropertyKeys;
@ -87,18 +87,18 @@ public class OAuth2LoginAutoConfiguration {
String userInfoUriValue = this.environment.getProperty(fullClientPropertyKey + "." + USER_INFO_URI_PROPERTY);
String userInfoConverterTypeValue = this.environment.getProperty(fullClientPropertyKey + "." + USER_INFO_CONVERTER_PROPERTY);
if (userInfoUriValue != null && userInfoConverterTypeValue != null) {
Class<? extends Converter> userInfoConverterType = ClassUtils.resolveClassName(
userInfoConverterTypeValue, this.getClass().getClassLoader()).asSubclass(Converter.class);
Converter<ClientHttpResponse, ? extends OAuth2User> userInfoConverter = null;
Class<? extends Function> userInfoConverterType = ClassUtils.resolveClassName(
userInfoConverterTypeValue, this.getClass().getClassLoader()).asSubclass(Function.class);
Function<ClientHttpResponse, ? extends OAuth2User> userInfoConverter = null;
if (AbstractOAuth2UserConverter.class.isAssignableFrom(userInfoConverterType)) {
Constructor<? extends Converter> oauth2UserConverterConstructor = ClassUtils.getConstructorIfAvailable(userInfoConverterType, String.class);
Constructor<? extends Function> oauth2UserConverterConstructor = ClassUtils.getConstructorIfAvailable(userInfoConverterType, String.class);
if (oauth2UserConverterConstructor != null) {
String userInfoNameAttributeKey = this.environment.getProperty(fullClientPropertyKey + "." + USER_INFO_NAME_ATTR_KEY_PROPERTY);
userInfoConverter = (Converter<ClientHttpResponse, ? extends OAuth2User>)oauth2UserConverterConstructor.newInstance(userInfoNameAttributeKey);
userInfoConverter = (Function<ClientHttpResponse, ? extends OAuth2User>)oauth2UserConverterConstructor.newInstance(userInfoNameAttributeKey);
}
}
if (userInfoConverter == null) {
userInfoConverter = (Converter<ClientHttpResponse, ? extends OAuth2User>)userInfoConverterType.newInstance();
userInfoConverter = (Function<ClientHttpResponse, ? extends OAuth2User>)userInfoConverterType.newInstance();
}
oauth2LoginConfigurer.userInfoEndpoint().userInfoTypeConverter(userInfoConverter, new URI(userInfoUriValue));
}