(私はトークンベアラとアクセステストし、それが働いていたが、私は、ベアラトークンなしでそれがアクセスできる必要があります):
- は新しい
PubliResource
注釈を作成します。
PublicResource
で注釈付けされたクラスの起動時にリストを作成し、トークンが検出されなかった場合でも明示的にそれらのクラスを要求させるようにしました。
import java.lang.annotation.*;
/***
* Used for marking a class accessible to a non-authorized user for
* @GET, @PUT, @POST, and @DELETE annotations
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface PublicResource {
}
それから私はAuthenticationTokenProcessingFilter
豆を作りました。
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.AdapterUtils;
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
import org.keycloak.representations.AccessToken;
import org.reflections.Reflections;
import org.reflections.util.ConfigurationBuilder;
import org.springframework.web.filter.GenericFilterBean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.*;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.TreeSet;
public class AuthenticationTokenProcessingFilter extends GenericFilterBean {
private static Set<String> nonAuthenticationWhiteListSet = new TreeSet<>();
static {
ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
configurationBuilder.forPackages("com.package.code.resources"); //IMPORTANT
Reflections reflections = new Reflections(configurationBuilder);
Set<Class<?>> annotated = reflections.getTypesAnnotatedWith(PublicResource.class);
for (Class<?> annotatedClass : annotated) {
if (!annotatedClass.isAnnotationPresent(Path.class)) {
continue;
}
String classPath = annotatedClass.getAnnotation(Path.class).value();
for (Method method : annotatedClass.getDeclaredMethods()) {
String fullPath = classPath;
if (method.isAnnotationPresent(GET.class)
|| method.isAnnotationPresent(POST.class)
|| method.isAnnotationPresent(PUT.class)
|| method.isAnnotationPresent(DELETE.class)) {
if (method.isAnnotationPresent(Path.class)) {
fullPath += method.getDeclaredAnnotation(Path.class).value();
}
fullPath = fullPath.replaceAll("\\{.*\\}", "[^/]+");
nonAuthenticationWhiteListSet.add(fullPath);
}
}
}
}
public AuthenticationTokenProcessingFilter() {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (!(request instanceof HttpServletRequest)) {
throw new RuntimeException("Expecting a HTTP request");
}
RefreshableKeycloakSecurityContext context = (RefreshableKeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
if (context == null) {
handleNoSecurityContext(request, response, chain);
return;
}
chain.doFilter(request, response);
}
private void handleNoSecurityContext(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String path = httpRequest.getPathInfo();
if (isPublicResource(path)) {
chain.doFilter(request, response);
return;
}
((HttpServletResponse) response).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
private boolean isPublicResource(String path) {
for (String regex : nonAuthenticationWhiteListSet) {
if (path.matches(regex)) {
return true;
}
}
return false;
}
}
私のメインクラスでは、これをフィルタとして登録するようにしました。
@Configuration
@EnableAutoConfiguration(exclude = {FallbackWebSecurityAutoConfiguration.class, SpringBootWebSecurityConfiguration.class, DataSourceAutoConfiguration.class})
@ComponentScan
@EnableAsync
public class MyApi {
//...other code plus the main method
@Bean
public AuthenticationTokenProcessingFilter authFilter() {
return new AuthenticationTokenProcessingFilter();
}
}