Complete AdminAuthenticationFilter

pull/137/head
johnniang 2019-03-28 00:03:48 +08:00
parent 9a9295d6c1
commit 42032e3b78
9 changed files with 151 additions and 18 deletions

View File

@ -78,8 +78,10 @@ public class HaloConfiguration {
}
@Bean
public FilterRegistrationBean<AdminAuthenticationFilter> adminAuthenticationFilter(HaloProperties haloProperties, ObjectMapper objectMapper) {
AdminAuthenticationFilter adminFilter = new AdminAuthenticationFilter();
public FilterRegistrationBean<AdminAuthenticationFilter> adminAuthenticationFilter(HaloProperties haloProperties,
ObjectMapper objectMapper,
StringCacheStore cacheStore) {
AdminAuthenticationFilter adminFilter = new AdminAuthenticationFilter(cacheStore);
// Set failure handler
adminFilter.setFailureHandler(new AdminAuthenticationFailureHandler(haloProperties.getProductionEnv(), objectMapper));

View File

@ -24,7 +24,7 @@ public class CorsFilter extends OncePerRequestFilter {
httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "*");
httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET, POST, PUT, DELETE, OPTION");
httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "false");
httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
httpServletResponse.setHeader(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "3600");
if (CorsUtils.isPreFlightRequest(httpServletRequest)) {

View File

@ -96,8 +96,10 @@ public class LocalFileHandler implements FileHandler {
// Build directory
String subDir = UPLOAD_SUB_DIR + year + File.separator + month + File.separator;
String originalBasename = FilenameUtils.getBasename(file.getOriginalFilename());
// Get basename
String basename = FilenameUtils.getBasename(file.getOriginalFilename()) + '-' + HaloUtils.randomUUIDWithoutDash();
String basename = originalBasename + '-' + HaloUtils.randomUUIDWithoutDash();
// Get extension
String extension = FilenameUtils.getExtension(file.getOriginalFilename());
@ -123,7 +125,7 @@ public class LocalFileHandler implements FileHandler {
// Build upload result
UploadResult uploadResult = new UploadResult();
uploadResult.setFilename(basename);
uploadResult.setFilename(originalBasename);
uploadResult.setFilePath(subFilePath);
uploadResult.setKey(subFilePath);
uploadResult.setSuffix(extension);

View File

@ -109,6 +109,7 @@ public interface PropertyEnum extends ValueEnum<String> {
|| type.isAssignableFrom(Double.class)
|| type.isAssignableFrom(Float.class)
|| type.isAssignableFrom(Enum.class)
|| type.isAssignableFrom(ValueEnum.class)
);
}
}

View File

@ -1,6 +1,18 @@
package cc.ryanc.halo.security.filter;
import cc.ryanc.halo.cache.StringCacheStore;
import cc.ryanc.halo.exception.AuthenticationException;
import cc.ryanc.halo.security.authentication.AuthenticationImpl;
import cc.ryanc.halo.security.context.SecurityContextHolder;
import cc.ryanc.halo.security.context.SecurityContextImpl;
import cc.ryanc.halo.security.handler.AuthenticationFailureHandler;
import cc.ryanc.halo.security.support.UserDetail;
import cc.ryanc.halo.utils.JsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
@ -8,6 +20,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Optional;
/**
* Admin authentication filter.
@ -16,15 +29,92 @@ import java.io.IOException;
*/
public class AdminAuthenticationFilter extends OncePerRequestFilter {
/**
* Admin session key.
*/
public final static String ADMIN_SESSION_KEY = "halo.admin.session";
/**
* Admin token header name.
*/
public final static String ADMIN_TOKEN_HEADER_NAME = "ADMIN-" + HttpHeaders.AUTHORIZATION;
/**
* Admin token param name.
*/
public final static String ADMIN_TOKEN_PARAM_NAME = "adminToken";
private AuthenticationFailureHandler failureHandler;
private final StringCacheStore cacheStore;
public AdminAuthenticationFilter(StringCacheStore cacheStore) {
this.cacheStore = cacheStore;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// TODO Handle admin authentication
filterChain.doFilter(request, response);
// Get token from request
String token = getTokenFromRequest(request);
if (StringUtils.isNotBlank(token)) {
// Valid the token
Optional<String> userDetailOptional = cacheStore.get(token);
if (!userDetailOptional.isPresent()) {
failureHandler.onFailure(request, response, new AuthenticationException("The token has been expired or not exist").setErrorData(token));
return;
}
UserDetail userDetail = JsonUtils.jsonToObject(userDetailOptional.get(), UserDetail.class);
// Set security
SecurityContextHolder.setContext(new SecurityContextImpl(new AuthenticationImpl(userDetail)));
filterChain.doFilter(request, response);
return;
}
// Get info from session
Object adminSessionValue = request.getSession().getAttribute(ADMIN_SESSION_KEY);
if (adminSessionValue instanceof UserDetail) {
// Convert to user detail
UserDetail userDetail = (UserDetail) adminSessionValue;
// Set security context
SecurityContextHolder.setContext(new SecurityContextImpl(new AuthenticationImpl(userDetail)));
filterChain.doFilter(request, response);
return;
}
failureHandler.onFailure(request, response, new AuthenticationException("You have to login before accessing admin api"));
}
public void setFailureHandler(AuthenticationFailureHandler failureHandler) {
this.failureHandler = failureHandler;
}
/**
* Gets token from request.
*
* @param request http servlet request must not be null
* @return token or null
*/
@Nullable
private String getTokenFromRequest(@NonNull HttpServletRequest request) {
Assert.notNull(request, "Http servlet request must not be null");
// Get from header
String token = request.getHeader(ADMIN_TOKEN_HEADER_NAME);
// Get from param
if (StringUtils.isBlank(token)) {
token = request.getParameter(ADMIN_TOKEN_PARAM_NAME);
}
return token;
}
}

View File

@ -1,13 +1,7 @@
package cc.ryanc.halo.security.handler;
import cc.ryanc.halo.exception.HaloException;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Authentication failure handler.
*
@ -19,8 +13,8 @@ public class AdminAuthenticationFailureHandler extends DefaultAuthenticationFail
super(productionEnv, objectMapper);
}
@Override
public void onFailure(HttpServletRequest request, HttpServletResponse response, HaloException exception) throws IOException, ServletException {
// TODO handler the admin authentication failure.
}
// @Override
// public void onFailure(HttpServletRequest request, HttpServletResponse response, HaloException exception) throws IOException, ServletException {
// // TODO handler the admin authentication failure.
// }
}

View File

@ -38,6 +38,7 @@ public class DefaultAuthenticationFailureHandler implements AuthenticationFailur
BaseResponse errorDetail = new BaseResponse();
errorDetail.setStatus(exception.getStatus().value());
errorDetail.setMessage(exception.getMessage());
if (!productionEnv) {

View File

@ -4,6 +4,7 @@ import cc.ryanc.halo.exception.MissingPropertyException;
import cc.ryanc.halo.model.dto.OptionOutputDTO;
import cc.ryanc.halo.model.entity.Option;
import cc.ryanc.halo.model.enums.PropertyEnum;
import cc.ryanc.halo.model.enums.ValueEnum;
import cc.ryanc.halo.model.params.OptionParam;
import cc.ryanc.halo.service.base.CrudService;
import com.qiniu.common.Zone;
@ -170,6 +171,7 @@ public interface OptionService extends CrudService<Option, Integer> {
* @param <T> value type
* @return value
*/
@NonNull
<T> Optional<T> getByKey(@NonNull String key, @NonNull Class<T> valueType);
/**
@ -180,6 +182,7 @@ public interface OptionService extends CrudService<Option, Integer> {
* @param <T> enum value type
* @return an optional enum value
*/
@NonNull
<T extends Enum<T>> Optional<T> getEnumByProperty(@NonNull PropertyEnum property, @NonNull Class<T> valueType);
/**
@ -191,7 +194,36 @@ public interface OptionService extends CrudService<Option, Integer> {
* @param <T> enum value type
* @return enum value
*/
<T extends Enum<T>> T getEnumByPropertyOrDefault(@NonNull PropertyEnum property, @NonNull Class<T> valueType, T defaultValue);
@Nullable
<T extends Enum<T>> T getEnumByPropertyOrDefault(@NonNull PropertyEnum property, @NonNull Class<T> valueType, @Nullable T defaultValue);
/**
* Gets value enum by property.
*
* @param property property must not be blank
* @param valueType enum value type must not be null
* @param enumType enum type must not be null
* @param <V> enum value type
* @param <E> value enum type
* @return an optional value enum value
*/
@NonNull
<V, E extends ValueEnum<V>> Optional<E> getValueEnumByProperty(@NonNull PropertyEnum property, @NonNull Class<V> valueType, @NonNull Class<E> enumType);
/**
* Gets value enum by property.
*
* @param property property must not be blank
* @param valueType enum value type must not be null
* @param enumType enum type must not be null
* @param defaultValue default value enum value
* @param <V> enum value type
* @param <E> value enum type
* @return value enum value or null if the default value is null
*/
@Nullable
<V, E extends ValueEnum<V>> E getValueEnumByPropertyOrDefault(@NonNull PropertyEnum property, @NonNull Class<V> valueType, @NonNull Class<E> enumType, @Nullable E defaultValue);
/**
* Gets post page size.

View File

@ -6,6 +6,7 @@ import cc.ryanc.halo.model.entity.Option;
import cc.ryanc.halo.model.enums.BlogProperties;
import cc.ryanc.halo.model.enums.PropertyEnum;
import cc.ryanc.halo.model.enums.QnYunProperties;
import cc.ryanc.halo.model.enums.ValueEnum;
import cc.ryanc.halo.model.params.OptionParam;
import cc.ryanc.halo.repository.OptionRepository;
import cc.ryanc.halo.service.OptionService;
@ -198,6 +199,16 @@ public class OptionServiceImpl extends AbstractCrudService<Option, Integer> impl
return getEnumByProperty(property, valueType).orElse(defaultValue);
}
@Override
public <V, E extends ValueEnum<V>> Optional<E> getValueEnumByProperty(PropertyEnum property, Class<V> valueType, Class<E> enumType) {
return getByProperty(property).map(value -> ValueEnum.valueToEnum(enumType, PropertyEnum.convertTo(value, valueType)));
}
@Override
public <V, E extends ValueEnum<V>> E getValueEnumByPropertyOrDefault(PropertyEnum property, Class<V> valueType, Class<E> enumType, E defaultValue) {
return getValueEnumByProperty(property, valueType, enumType).orElse(defaultValue);
}
@Override
public int getPostPageSize() {
try {