Reorganize interceptor
This commit is contained in:
@@ -151,7 +151,7 @@ public class GrpcServerApplicationTests {
|
||||
@Lazy
|
||||
SimpleGrpc.SimpleBlockingStub basic(GrpcChannelFactory channels) {
|
||||
return SimpleGrpc.newBlockingStub(channels.createChannel("basic", ChannelBuilderOptions.defaults()
|
||||
.withInterceptors(List.of(new BasicAuthenticationInterceptor("user", "user")))));
|
||||
.withInterceptors(List.of(new BasicAuthenticationInterceptor("user", "user")))));
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import io.grpc.ForwardingServerCallListener;
|
||||
import io.grpc.Metadata;
|
||||
import io.grpc.ServerCall;
|
||||
import io.grpc.ServerCall.Listener;
|
||||
@@ -37,11 +36,11 @@ import io.grpc.ServerInterceptor;
|
||||
* An interceptor that extracts the authentication credentials from the gRPC request
|
||||
* headers and metadata, authenticates the user, and sets the authentication in the
|
||||
* SecurityContext. This interceptor should be registered with the gRPC server to handle
|
||||
* authentication.
|
||||
* authentication and authorization for gRPC requests.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class AuthenticationServerInterceptor implements ServerInterceptor, Ordered {
|
||||
public class AuthenticationProcessInterceptor implements ServerInterceptor, Ordered {
|
||||
|
||||
private final AuthenticationManager authenticationManager;
|
||||
|
||||
@@ -54,7 +53,7 @@ public class AuthenticationServerInterceptor implements ServerInterceptor, Order
|
||||
return GrpcSecurity.CONTEXT_FILTER_ORDER - 10;
|
||||
}
|
||||
|
||||
public AuthenticationServerInterceptor(AuthenticationManager authenticationManager,
|
||||
public AuthenticationProcessInterceptor(AuthenticationManager authenticationManager,
|
||||
GrpcAuthenticationExtractor extractor, AuthorizationManager<CallContext> authorizationManager) {
|
||||
this.authenticationManager = authenticationManager;
|
||||
this.extractor = extractor;
|
||||
@@ -72,56 +71,26 @@ public class AuthenticationServerInterceptor implements ServerInterceptor, Order
|
||||
}
|
||||
|
||||
if (this.authorizationManager != null) {
|
||||
CallContext context = new CallContext(headers, call.getAttributes(), call.getMethodDescriptor());
|
||||
if (user == null) {
|
||||
// Maybe just throw BadCredentialsException (authentication manager would
|
||||
// have to make the anonymous user)?
|
||||
user = new AnonymousAuthenticationToken("anonymous", "anonymous",
|
||||
AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
|
||||
}
|
||||
return new AuthenticatedListener<ReqT>(next.startCall(call, headers), this.authorizationManager,
|
||||
new CallContext(headers, call.getAttributes(), call.getMethodDescriptor()), user);
|
||||
}
|
||||
return new AuthenticatedListener<ReqT>(next.startCall(call, headers), null,
|
||||
new CallContext(headers, call.getAttributes(), call.getMethodDescriptor()), user);
|
||||
}
|
||||
|
||||
static class AuthenticatedListener<ReqT> extends ForwardingServerCallListener<ReqT> {
|
||||
|
||||
private final Listener<ReqT> delegate;
|
||||
|
||||
private final CallContext context;
|
||||
|
||||
private final Authentication authentication;
|
||||
|
||||
private final AuthorizationManager<CallContext> authorizationManager;
|
||||
|
||||
AuthenticatedListener(io.grpc.ServerCall.Listener<ReqT> delegate,
|
||||
AuthorizationManager<CallContext> authorizationManager, CallContext context, Authentication user) {
|
||||
this.delegate = delegate;
|
||||
this.authorizationManager = authorizationManager;
|
||||
this.context = context;
|
||||
this.authentication = user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReady() {
|
||||
if (this.authentication == null || !this.authentication.isAuthenticated()) {
|
||||
throw new BadCredentialsException("not authenticated");
|
||||
}
|
||||
else {
|
||||
if (!this.authorizationManager.authorize(() -> this.authentication, this.context).isGranted()) {
|
||||
if (this.authentication instanceof AnonymousAuthenticationToken) {
|
||||
throw new BadCredentialsException("not authenticated");
|
||||
}
|
||||
throw new AccessDeniedException("not allowed");
|
||||
Authentication authentication = user;
|
||||
if (!this.authorizationManager.authorize(() -> authentication, context).isGranted()) {
|
||||
if (user instanceof AnonymousAuthenticationToken) {
|
||||
throw new BadCredentialsException("not authenticated");
|
||||
}
|
||||
throw new AccessDeniedException("not allowed");
|
||||
}
|
||||
super.onReady();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Listener<ReqT> delegate() {
|
||||
return this.delegate;
|
||||
}
|
||||
else if (user == null || !user.isAuthenticated()) {
|
||||
throw new BadCredentialsException("not authenticated");
|
||||
}
|
||||
|
||||
return next.startCall(call, headers);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -52,7 +52,7 @@ import io.micrometer.observation.ObservationRegistry;
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public final class GrpcSecurity
|
||||
extends AbstractConfiguredSecurityBuilder<AuthenticationServerInterceptor, GrpcSecurity> {
|
||||
extends AbstractConfiguredSecurityBuilder<AuthenticationProcessInterceptor, GrpcSecurity> {
|
||||
|
||||
/**
|
||||
* A constant key used for storing and retrieving the "Authorization" header from gRPC
|
||||
@@ -100,7 +100,7 @@ public final class GrpcSecurity
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthenticationServerInterceptor performBuild() throws Exception {
|
||||
protected AuthenticationProcessInterceptor performBuild() throws Exception {
|
||||
if (this.authenticationManager != null) {
|
||||
setSharedObject(AuthenticationManager.class, this.authenticationManager);
|
||||
}
|
||||
@@ -115,7 +115,7 @@ public final class GrpcSecurity
|
||||
}
|
||||
}
|
||||
this.authenticationExtractors.sort(AnnotationAwareOrderComparator.INSTANCE);
|
||||
return new AuthenticationServerInterceptor(getSharedObject(AuthenticationManager.class),
|
||||
return new AuthenticationProcessInterceptor(getSharedObject(AuthenticationManager.class),
|
||||
new CompositeAuthenticationExtractor(this.authenticationExtractors), this.authorizationManager);
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ public final class GrpcSecurity
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "removal" })
|
||||
private <C extends SecurityConfigurerAdapter<AuthenticationServerInterceptor, GrpcSecurity>> C getOrApply(
|
||||
private <C extends SecurityConfigurerAdapter<AuthenticationProcessInterceptor, GrpcSecurity>> C getOrApply(
|
||||
C configurer) throws Exception {
|
||||
C existingConfig = (C) getConfigurer(configurer.getClass());
|
||||
if (existingConfig != null) {
|
||||
|
||||
@@ -22,8 +22,8 @@ import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
|
||||
public final class HttpBasicConfigurer<H extends SecurityBuilder<AuthenticationServerInterceptor>>
|
||||
extends SecurityConfigurerAdapter<AuthenticationServerInterceptor, H> {
|
||||
public final class HttpBasicConfigurer<H extends SecurityBuilder<AuthenticationProcessInterceptor>>
|
||||
extends SecurityConfigurerAdapter<AuthenticationProcessInterceptor, H> {
|
||||
|
||||
private final ApplicationContext context;
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@ import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
||||
|
||||
public final class PreAuthConfigurer<H extends SecurityBuilder<AuthenticationServerInterceptor>>
|
||||
extends SecurityConfigurerAdapter<AuthenticationServerInterceptor, H> {
|
||||
public final class PreAuthConfigurer<H extends SecurityBuilder<AuthenticationProcessInterceptor>>
|
||||
extends SecurityConfigurerAdapter<AuthenticationProcessInterceptor, H> {
|
||||
|
||||
private final ApplicationContext context;
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.PatternMatchUtils;
|
||||
import org.springframework.util.function.SingletonSupplier;
|
||||
|
||||
public class RequestMapperConfigurer extends SecurityConfigurerAdapter<AuthenticationServerInterceptor, GrpcSecurity> {
|
||||
public class RequestMapperConfigurer extends SecurityConfigurerAdapter<AuthenticationProcessInterceptor, GrpcSecurity> {
|
||||
|
||||
private List<AuthorizedCall> authorizedCalls = new ArrayList<>();
|
||||
|
||||
@@ -46,12 +46,12 @@ public class RequestMapperConfigurer extends SecurityConfigurerAdapter<Authentic
|
||||
public RequestMapperConfigurer(ApplicationContext context) throws Exception {
|
||||
if (context.getBeanNamesForType(AuthorizationEventPublisher.class).length > 0) {
|
||||
this.publisher = context.getBean(AuthorizationEventPublisher.class);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
this.publisher = new SpringAuthorizationEventPublisher(context);
|
||||
}
|
||||
this.roleHierarchy = SingletonSupplier.of(() -> (context.getBeanNamesForType(RoleHierarchy.class).length > 0)
|
||||
? context.getBean(RoleHierarchy.class)
|
||||
: new NullRoleHierarchy());
|
||||
? context.getBean(RoleHierarchy.class) : new NullRoleHierarchy());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -150,6 +150,7 @@ public class RequestMapperConfigurer extends SecurityConfigurerAdapter<Authentic
|
||||
public static class RequestMapperAuthorizationManager implements AuthorizationManager<CallContext> {
|
||||
|
||||
private final List<AuthorizedCall> authorizedCalls;
|
||||
|
||||
private final AuthorizationEventPublisher publisher;
|
||||
|
||||
public RequestMapperAuthorizationManager(List<AuthorizedCall> authorizedCalls,
|
||||
|
||||
Reference in New Issue
Block a user