Add tryAuthUrlMethodPatterns for skipping authentication failure if necessary

pull/137/head
johnniang 2019-03-30 23:27:37 +08:00
parent 78b6fe5fe2
commit a0738f9ea2
3 changed files with 96 additions and 21 deletions

View File

@ -19,6 +19,7 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.client.RestTemplate;
@ -92,10 +93,13 @@ public class HaloConfiguration {
@Bean
public FilterRegistrationBean<ApiAuthenticationFilter> apiAuthenticationFilter(HaloProperties haloProperties, ObjectMapper objectMapper) {
ApiAuthenticationFilter apiFilter = new ApiAuthenticationFilter();
DefaultAuthenticationFailureHandler failureHandler = new DefaultAuthenticationFailureHandler();
failureHandler.setProductionEnv(haloProperties.getProductionEnv());
failureHandler.setObjectMapper(objectMapper);
// Set failure handler
apiFilter.setFailureHandler(new DefaultAuthenticationFailureHandler()
.setProductionEnv(haloProperties.getProductionEnv())
.setObjectMapper(objectMapper));
apiFilter.setFailureHandler(failureHandler);
FilterRegistrationBean<ApiAuthenticationFilter> authenticationFilter = new FilterRegistrationBean<>();
authenticationFilter.setFilter(apiFilter);
@ -110,11 +114,16 @@ public class HaloConfiguration {
HaloProperties haloProperties,
ObjectMapper objectMapper) {
AdminAuthenticationFilter adminAuthenticationFilter = new AdminAuthenticationFilter(cacheStore, userService, haloProperties);
AdminAuthenticationFailureHandler failureHandler = new AdminAuthenticationFailureHandler();
failureHandler.setProductionEnv(haloProperties.getProductionEnv());
failureHandler.setObjectMapper(objectMapper);
// Config the admin filter
adminAuthenticationFilter.addExcludeUrlPatterns("/admin/api/login")
.setFailureHandler(new AdminAuthenticationFailureHandler()
.setProductionEnv(haloProperties.getProductionEnv())
.setObjectMapper(objectMapper));
adminAuthenticationFilter.addExcludeUrlPatterns("/admin/api/login");
adminAuthenticationFilter.addTryAuthUrlMethodPattern("/admin/api/comments", HttpMethod.POST.name());
adminAuthenticationFilter.setFailureHandler(
failureHandler);
FilterRegistrationBean<AdminAuthenticationFilter> authenticationFilter = new FilterRegistrationBean<>();
authenticationFilter.setFilter(adminAuthenticationFilter);

View File

@ -12,6 +12,7 @@ import cc.ryanc.halo.security.handler.DefaultAuthenticationFailureHandler;
import cc.ryanc.halo.security.support.UserDetail;
import cc.ryanc.halo.service.UserService;
import cc.ryanc.halo.utils.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.NonNull;
@ -32,6 +33,7 @@ import java.util.*;
*
* @author johnniang
*/
@Slf4j
public class AdminAuthenticationFilter extends OncePerRequestFilter {
/**
@ -59,7 +61,15 @@ public class AdminAuthenticationFilter extends OncePerRequestFilter {
private final AntPathMatcher antPathMatcher;
private Set<String> excludeUrlPatterns = new HashSet<>(1);
/**
* Exclude url patterns.
*/
private Set<String> excludeUrlPatterns = new HashSet<>(2);
/**
* Try authenticating url, method patterns.
*/
private Map<String, String> tryAuthUrlMethodPatterns = new HashMap<>(2);
public AdminAuthenticationFilter(StringCacheStore cacheStore,
UserService userService,
@ -121,14 +131,42 @@ public class AdminAuthenticationFilter extends OncePerRequestFilter {
return;
}
if (shouldSkipAuthenticateFailure(request)) {
// If should skip this authentication failure
log.debug("Skipping authentication failure, url: [{}], method: [{}]", request.getServletPath(), request.getMethod());
filterChain.doFilter(request, response);
return;
}
getFailureHandler().onFailure(request, response, new AuthenticationException("You have to login before accessing admin api"));
}
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
Assert.notNull(request, "Http servlet request must not be null");
return excludeUrlPatterns.stream().anyMatch(p -> antPathMatcher.match(p, request.getServletPath()));
}
/**
* Should skip authentication failure.
*
* @param request http servlet request must not be null.
* @return true if the request should skip authentication failure; false otherwise
*/
protected boolean shouldSkipAuthenticateFailure(@NonNull HttpServletRequest request) {
Assert.notNull(request, "Http servlet request must not be null");
for (String url : tryAuthUrlMethodPatterns.keySet()) {
if (antPathMatcher.match(url, request.getServletPath())
&& tryAuthUrlMethodPatterns.get(url).equalsIgnoreCase(request.getMethod())) {
return true;
}
}
return false;
}
/**
* Gets authentication failure handler. (Default: @DefaultAuthenticationFailureHandler)
*
@ -137,8 +175,13 @@ public class AdminAuthenticationFilter extends OncePerRequestFilter {
public AuthenticationFailureHandler getFailureHandler() {
if (failureHandler == null) {
synchronized (this) {
// Create default authentication failure handler
failureHandler = new DefaultAuthenticationFailureHandler().setProductionEnv(haloProperties.getProductionEnv());
if (failureHandler == null) {
// Create default authentication failure handler
DefaultAuthenticationFailureHandler failureHandler = new DefaultAuthenticationFailureHandler();
failureHandler.setProductionEnv(haloProperties.getProductionEnv());
this.failureHandler = failureHandler;
}
}
}
return failureHandler;
@ -149,9 +192,10 @@ public class AdminAuthenticationFilter extends OncePerRequestFilter {
*
* @param failureHandler authentication failure handler
*/
public AdminAuthenticationFilter setFailureHandler(AuthenticationFailureHandler failureHandler) {
public void setFailureHandler(@NonNull AuthenticationFailureHandler failureHandler) {
Assert.notNull(failureHandler, "Authentication failure handler must not be null");
this.failureHandler = failureHandler;
return this;
}
/**
@ -159,11 +203,10 @@ public class AdminAuthenticationFilter extends OncePerRequestFilter {
*
* @param excludeUrlPatterns exclude urls
*/
public AdminAuthenticationFilter setExcludeUrlPatterns(Collection<String> excludeUrlPatterns) {
public void setExcludeUrlPatterns(@NonNull Collection<String> excludeUrlPatterns) {
Assert.notNull(excludeUrlPatterns, "Exclude url patterns must not be null");
this.excludeUrlPatterns = new HashSet<>(excludeUrlPatterns);
return this;
}
/**
@ -171,11 +214,32 @@ public class AdminAuthenticationFilter extends OncePerRequestFilter {
*
* @param excludeUrlPatterns exclude urls
*/
public AdminAuthenticationFilter addExcludeUrlPatterns(String... excludeUrlPatterns) {
public void addExcludeUrlPatterns(@NonNull String... excludeUrlPatterns) {
Assert.notNull(excludeUrlPatterns, "Exclude url patterns must not be null");
Collections.addAll(this.excludeUrlPatterns, excludeUrlPatterns);
return this;
}
/**
* Gets exclude url patterns.
*
* @return exclude url patterns.
*/
public Set<String> getExcludeUrlPatterns() {
return excludeUrlPatterns;
}
/**
* Adds try authenticating url method pattern.
*
* @param url url must not be blank
* @param method method must not be blank
*/
public void addTryAuthUrlMethodPattern(@NonNull String url, @NonNull String method) {
Assert.hasText(url, "Try authenticating url must not be blank");
Assert.hasText(method, "Try authenticating method must not be blank");
tryAuthUrlMethodPatterns.put(url, method);
}
/**

View File

@ -55,17 +55,19 @@ public class DefaultAuthenticationFailureHandler implements AuthenticationFailur
* Sets custom object mapper.
*
* @param objectMapper object mapper
* @return current authentication failure handler
*/
public DefaultAuthenticationFailureHandler setObjectMapper(ObjectMapper objectMapper) {
public void setObjectMapper(ObjectMapper objectMapper) {
Assert.notNull(objectMapper, "Object mapper must not be null");
this.objectMapper = objectMapper;
return this;
}
public DefaultAuthenticationFailureHandler setProductionEnv(boolean productionEnv) {
/**
* Sets production environment.
*
* @param productionEnv production environment
*/
public void setProductionEnv(boolean productionEnv) {
this.productionEnv = productionEnv;
return this;
}
}