Refactor authentication filters

pull/146/head
johnniang 2019-05-06 19:00:39 +08:00
parent cfc8207919
commit 1e15f21e88
3 changed files with 61 additions and 63 deletions

View File

@ -6,10 +6,17 @@ import org.springframework.util.AntPathMatcher;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import run.halo.app.config.properties.HaloProperties; import run.halo.app.config.properties.HaloProperties;
import run.halo.app.exception.NotInstallException;
import run.halo.app.model.properties.PrimaryProperties;
import run.halo.app.security.handler.AuthenticationFailureHandler; import run.halo.app.security.handler.AuthenticationFailureHandler;
import run.halo.app.security.handler.DefaultAuthenticationFailureHandler; import run.halo.app.security.handler.DefaultAuthenticationFailureHandler;
import run.halo.app.service.OptionService;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*; import java.util.*;
/** /**
@ -36,8 +43,12 @@ public abstract class AbstractAuthenticationFilter extends OncePerRequestFilter
private final HaloProperties haloProperties; private final HaloProperties haloProperties;
protected AbstractAuthenticationFilter(HaloProperties haloProperties) { private final OptionService optionService;
protected AbstractAuthenticationFilter(HaloProperties haloProperties,
OptionService optionService) {
this.haloProperties = haloProperties; this.haloProperties = haloProperties;
this.optionService = optionService;
antPathMatcher = new AntPathMatcher(); antPathMatcher = new AntPathMatcher();
} }
@ -154,4 +165,16 @@ public abstract class AbstractAuthenticationFilter extends OncePerRequestFilter
this.failureHandler = failureHandler; this.failureHandler = failureHandler;
} }
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// Check whether the blog is installed or not
Boolean isInstalled = optionService.getByPropertyOrDefault(PrimaryProperties.IS_INSTALLED, Boolean.class, false);
if (!isInstalled) {
// If not installed
getFailureHandler().onFailure(request, response, new NotInstallException("The blog has not been initialized yet!"));
return;
}
}
} }

View File

@ -4,14 +4,11 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import run.halo.app.cache.StringCacheStore; import run.halo.app.cache.StringCacheStore;
import run.halo.app.config.properties.HaloProperties; import run.halo.app.config.properties.HaloProperties;
import run.halo.app.exception.AuthenticationException; import run.halo.app.exception.AuthenticationException;
import run.halo.app.exception.NotInstallException;
import run.halo.app.model.entity.User; import run.halo.app.model.entity.User;
import run.halo.app.model.properties.PrimaryProperties;
import run.halo.app.security.authentication.AuthenticationImpl; import run.halo.app.security.authentication.AuthenticationImpl;
import run.halo.app.security.context.SecurityContextHolder; import run.halo.app.security.context.SecurityContextHolder;
import run.halo.app.security.context.SecurityContextImpl; import run.halo.app.security.context.SecurityContextImpl;
@ -58,7 +55,7 @@ public class AdminAuthenticationFilter extends AbstractAuthenticationFilter {
/** /**
* Admin token param name. * Admin token param name.
*/ */
public final static String ADMIN_TOKEN_QUERY_NAME = "adminToken"; public final static String ADMIN_TOKEN_QUERY_NAME = "admin_token";
private final HaloProperties haloProperties; private final HaloProperties haloProperties;
@ -72,7 +69,7 @@ public class AdminAuthenticationFilter extends AbstractAuthenticationFilter {
UserService userService, UserService userService,
HaloProperties haloProperties, HaloProperties haloProperties,
OptionService optionService) { OptionService optionService) {
super(haloProperties); super(haloProperties, optionService);
this.cacheStore = cacheStore; this.cacheStore = cacheStore;
this.userService = userService; this.userService = userService;
this.haloProperties = haloProperties; this.haloProperties = haloProperties;
@ -82,59 +79,45 @@ public class AdminAuthenticationFilter extends AbstractAuthenticationFilter {
@Override @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// Check whether the blog is installed or not super.doFilterInternal(request, response, filterChain);
Boolean isInstalled = optionService.getByPropertyOrDefault(PrimaryProperties.IS_INSTALLED, Boolean.class, false);
if (!isInstalled) { if (haloProperties.isAuthEnabled()) {
// If not installed // Get token from request
getFailureHandler().onFailure(request, response, new NotInstallException("The blog has not been initialized yet!")); String token = getTokenFromRequest(request);
return;
}
if (!haloProperties.isAuthEnabled()) { if (StringUtils.isBlank(token)) {
if (!shouldSkipAuthenticateFailure(request)) {
getFailureHandler().onFailure(request, response, new AuthenticationException("You have to login before accessing admin api"));
return;
}
} else {
// Get user id from cache
Optional<Integer> optionalUserId = cacheStore.getAny(SecurityUtils.buildTokenAccessKey(token), Integer.class);
if (!optionalUserId.isPresent()) {
getFailureHandler().onFailure(request, response, new AuthenticationException("The token has been expired or not exist").setErrorData(token));
return;
}
// Get the user
User user = userService.getById(optionalUserId.get());
// Build user detail
UserDetail userDetail = new UserDetail(user);
// Set security
SecurityContextHolder.setContext(new SecurityContextImpl(new AuthenticationImpl(userDetail)));
}
} else {
// Set security
userService.getCurrentUser().ifPresent(user -> userService.getCurrentUser().ifPresent(user ->
SecurityContextHolder.setContext(new SecurityContextImpl(new AuthenticationImpl(new UserDetail(user))))); SecurityContextHolder.setContext(new SecurityContextImpl(new AuthenticationImpl(new UserDetail(user)))));
// If authentication disabled
filterChain.doFilter(request, response);
return;
} }
// Get token from request filterChain.doFilter(request, response);
String token = getTokenFromRequest(request);
if (StringUtils.isNotBlank(token)) { // Clear context
SecurityContextHolder.clearContext();
// Get user id from cache
Optional<Integer> optionalUserId = cacheStore.getAny(SecurityUtils.buildTokenAccessKey(token), Integer.class);
if (!optionalUserId.isPresent()) {
getFailureHandler().onFailure(request, response, new AuthenticationException("The token has been expired or not exist").setErrorData(token));
return;
}
// Get the user
User user = userService.getById(optionalUserId.get());
// Build user detail
UserDetail userDetail = new UserDetail(user);
// Set security
SecurityContextHolder.setContext(new SecurityContextImpl(new AuthenticationImpl(userDetail)));
filterChain.doFilter(request, response);
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 @Override

View File

@ -8,9 +8,7 @@ import org.springframework.util.Assert;
import run.halo.app.config.properties.HaloProperties; import run.halo.app.config.properties.HaloProperties;
import run.halo.app.exception.AuthenticationException; import run.halo.app.exception.AuthenticationException;
import run.halo.app.exception.ForbiddenException; import run.halo.app.exception.ForbiddenException;
import run.halo.app.exception.NotInstallException;
import run.halo.app.model.properties.OtherProperties; import run.halo.app.model.properties.OtherProperties;
import run.halo.app.model.properties.PrimaryProperties;
import run.halo.app.service.OptionService; import run.halo.app.service.OptionService;
import javax.servlet.FilterChain; import javax.servlet.FilterChain;
@ -30,26 +28,20 @@ public class ApiAuthenticationFilter extends AbstractAuthenticationFilter {
public final static String API_TOKEN_HEADER_NAME = "API-" + HttpHeaders.AUTHORIZATION; public final static String API_TOKEN_HEADER_NAME = "API-" + HttpHeaders.AUTHORIZATION;
public final static String API_TOKEN_QUERY_NAME = "apiToken"; public final static String API_TOKEN_QUERY_NAME = "api_token";
private final OptionService optionService; private final OptionService optionService;
public ApiAuthenticationFilter(HaloProperties haloProperties, public ApiAuthenticationFilter(HaloProperties haloProperties,
OptionService optionService) { OptionService optionService) {
super(haloProperties); super(haloProperties, optionService);
this.optionService = optionService; this.optionService = optionService;
} }
@Override @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// Check whether the blog is installed or not
Boolean isInstalled = optionService.getByPropertyOrDefault(PrimaryProperties.IS_INSTALLED, Boolean.class, false);
if (!isInstalled) { super.doFilterInternal(request, response, filterChain);
// If not installed
getFailureHandler().onFailure(request, response, new NotInstallException("The blog has not been initialized yet!"));
return;
}
// Get token // Get token
String token = getTokenFromRequest(request); String token = getTokenFromRequest(request);