mirror of https://github.com/halo-dev/halo
Refactor AdminAuthenticationFilter
parent
e973bf2200
commit
523afaebe4
|
@ -69,7 +69,9 @@ public class HaloConfiguration {
|
||||||
public FilterRegistrationBean<ApiAuthenticationFilter> apiAuthenticationFilter(HaloProperties haloProperties, ObjectMapper objectMapper) {
|
public FilterRegistrationBean<ApiAuthenticationFilter> apiAuthenticationFilter(HaloProperties haloProperties, ObjectMapper objectMapper) {
|
||||||
ApiAuthenticationFilter apiFilter = new ApiAuthenticationFilter();
|
ApiAuthenticationFilter apiFilter = new ApiAuthenticationFilter();
|
||||||
// Set failure handler
|
// Set failure handler
|
||||||
apiFilter.setFailureHandler(new DefaultAuthenticationFailureHandler(haloProperties.getProductionEnv(), objectMapper));
|
apiFilter.setFailureHandler(new DefaultAuthenticationFailureHandler()
|
||||||
|
.setProductionEnv(haloProperties.getProductionEnv())
|
||||||
|
.setObjectMapper(objectMapper));
|
||||||
|
|
||||||
FilterRegistrationBean<ApiAuthenticationFilter> authenticationFilter = new FilterRegistrationBean<>();
|
FilterRegistrationBean<ApiAuthenticationFilter> authenticationFilter = new FilterRegistrationBean<>();
|
||||||
authenticationFilter.setFilter(apiFilter);
|
authenticationFilter.setFilter(apiFilter);
|
||||||
|
@ -79,19 +81,19 @@ public class HaloConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public FilterRegistrationBean<AdminAuthenticationFilter> adminAuthenticationFilter(HaloProperties haloProperties,
|
public FilterRegistrationBean<AdminAuthenticationFilter> adminAuthenticationFilter(StringCacheStore cacheStore,
|
||||||
ObjectMapper objectMapper,
|
UserService userService,
|
||||||
StringCacheStore cacheStore,
|
HaloProperties haloProperties,
|
||||||
UserService userService) {
|
ObjectMapper objectMapper) {
|
||||||
AdminAuthenticationFilter adminFilter = new AdminAuthenticationFilter(cacheStore, userService, "/admin/api/login");
|
AdminAuthenticationFilter adminAuthenticationFilter = new AdminAuthenticationFilter(cacheStore, userService, haloProperties);
|
||||||
// Set auth enabled
|
// Config the admin filter
|
||||||
adminFilter.setAuthEnabled(haloProperties.getAuthEnabled());
|
adminAuthenticationFilter.setExcludeUrlPatterns("/admin/api/login")
|
||||||
|
.setFailureHandler(new AdminAuthenticationFailureHandler()
|
||||||
// Set failure handler
|
.setProductionEnv(haloProperties.getProductionEnv())
|
||||||
adminFilter.setFailureHandler(new AdminAuthenticationFailureHandler(haloProperties.getProductionEnv(), objectMapper));
|
.setObjectMapper(objectMapper));
|
||||||
|
|
||||||
FilterRegistrationBean<AdminAuthenticationFilter> authenticationFilter = new FilterRegistrationBean<>();
|
FilterRegistrationBean<AdminAuthenticationFilter> authenticationFilter = new FilterRegistrationBean<>();
|
||||||
authenticationFilter.setFilter(adminFilter);
|
authenticationFilter.setFilter(adminAuthenticationFilter);
|
||||||
authenticationFilter.addUrlPatterns("/admin/*");
|
authenticationFilter.addUrlPatterns("/admin/*");
|
||||||
authenticationFilter.setOrder(1);
|
authenticationFilter.setOrder(1);
|
||||||
return authenticationFilter;
|
return authenticationFilter;
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package cc.ryanc.halo.security.filter;
|
package cc.ryanc.halo.security.filter;
|
||||||
|
|
||||||
import cc.ryanc.halo.cache.StringCacheStore;
|
import cc.ryanc.halo.cache.StringCacheStore;
|
||||||
|
import cc.ryanc.halo.config.properties.HaloProperties;
|
||||||
import cc.ryanc.halo.exception.AuthenticationException;
|
import cc.ryanc.halo.exception.AuthenticationException;
|
||||||
import cc.ryanc.halo.model.entity.User;
|
import cc.ryanc.halo.model.entity.User;
|
||||||
import cc.ryanc.halo.security.authentication.AuthenticationImpl;
|
import cc.ryanc.halo.security.authentication.AuthenticationImpl;
|
||||||
import cc.ryanc.halo.security.context.SecurityContextHolder;
|
import cc.ryanc.halo.security.context.SecurityContextHolder;
|
||||||
import cc.ryanc.halo.security.context.SecurityContextImpl;
|
import cc.ryanc.halo.security.context.SecurityContextImpl;
|
||||||
import cc.ryanc.halo.security.handler.AuthenticationFailureHandler;
|
import cc.ryanc.halo.security.handler.AuthenticationFailureHandler;
|
||||||
|
import cc.ryanc.halo.security.handler.DefaultAuthenticationFailureHandler;
|
||||||
import cc.ryanc.halo.security.support.UserDetail;
|
import cc.ryanc.halo.security.support.UserDetail;
|
||||||
import cc.ryanc.halo.service.UserService;
|
import cc.ryanc.halo.service.UserService;
|
||||||
import cc.ryanc.halo.utils.JsonUtils;
|
import cc.ryanc.halo.utils.JsonUtils;
|
||||||
|
@ -49,30 +51,29 @@ public class AdminAuthenticationFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
private AuthenticationFailureHandler failureHandler;
|
private AuthenticationFailureHandler failureHandler;
|
||||||
|
|
||||||
/**
|
private final HaloProperties haloProperties;
|
||||||
* Authentication enabled.
|
|
||||||
*/
|
|
||||||
private boolean authEnabled = true;
|
|
||||||
|
|
||||||
private final StringCacheStore cacheStore;
|
private final StringCacheStore cacheStore;
|
||||||
|
|
||||||
private final UserService userService;
|
private final UserService userService;
|
||||||
|
|
||||||
private final Collection<String> excludeUrlPatterns;
|
|
||||||
|
|
||||||
private final AntPathMatcher antPathMatcher;
|
private final AntPathMatcher antPathMatcher;
|
||||||
|
|
||||||
public AdminAuthenticationFilter(StringCacheStore cacheStore, UserService userService, String... excludeUrls) {
|
private Collection<String> excludeUrlPatterns;
|
||||||
|
|
||||||
|
public AdminAuthenticationFilter(StringCacheStore cacheStore,
|
||||||
|
UserService userService,
|
||||||
|
HaloProperties haloProperties) {
|
||||||
this.cacheStore = cacheStore;
|
this.cacheStore = cacheStore;
|
||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
this.excludeUrlPatterns = excludeUrls == null ? Collections.emptyList() : Collections.unmodifiableCollection(Arrays.asList(excludeUrls));
|
this.haloProperties = haloProperties;
|
||||||
antPathMatcher = new AntPathMatcher();
|
antPathMatcher = new AntPathMatcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
@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 {
|
||||||
|
|
||||||
if (!authEnabled) {
|
if (!haloProperties.getAuthEnabled()) {
|
||||||
List<User> users = userService.listAll();
|
List<User> users = userService.listAll();
|
||||||
if (!users.isEmpty()) {
|
if (!users.isEmpty()) {
|
||||||
// Set security context
|
// Set security context
|
||||||
|
@ -93,7 +94,7 @@ public class AdminAuthenticationFilter extends OncePerRequestFilter {
|
||||||
Optional<String> userDetailOptional = cacheStore.get(token);
|
Optional<String> userDetailOptional = cacheStore.get(token);
|
||||||
|
|
||||||
if (!userDetailOptional.isPresent()) {
|
if (!userDetailOptional.isPresent()) {
|
||||||
failureHandler.onFailure(request, response, new AuthenticationException("The token has been expired or not exist").setErrorData(token));
|
getFailureHandler().onFailure(request, response, new AuthenticationException("The token has been expired or not exist").setErrorData(token));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +121,7 @@ public class AdminAuthenticationFilter extends OncePerRequestFilter {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
failureHandler.onFailure(request, response, new AuthenticationException("You have to login before accessing admin api"));
|
getFailureHandler().onFailure(request, response, new AuthenticationException("You have to login before accessing admin api"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -128,12 +129,39 @@ public class AdminAuthenticationFilter extends OncePerRequestFilter {
|
||||||
return excludeUrlPatterns.stream().anyMatch(p -> antPathMatcher.match(p, request.getServletPath()));
|
return excludeUrlPatterns.stream().anyMatch(p -> antPathMatcher.match(p, request.getServletPath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFailureHandler(AuthenticationFailureHandler failureHandler) {
|
/**
|
||||||
this.failureHandler = failureHandler;
|
* Gets authentication failure handler. (Default: @DefaultAuthenticationFailureHandler)
|
||||||
|
*
|
||||||
|
* @return authentication failure handler
|
||||||
|
*/
|
||||||
|
public AuthenticationFailureHandler getFailureHandler() {
|
||||||
|
if (failureHandler == null) {
|
||||||
|
synchronized (this) {
|
||||||
|
// Create default authentication failure handler
|
||||||
|
failureHandler = new DefaultAuthenticationFailureHandler().setProductionEnv(haloProperties.getProductionEnv());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return failureHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAuthEnabled(boolean authEnabled) {
|
/**
|
||||||
this.authEnabled = authEnabled;
|
* Sets authentication failure handler.
|
||||||
|
*
|
||||||
|
* @param failureHandler authentication failure handler
|
||||||
|
*/
|
||||||
|
public AdminAuthenticationFilter setFailureHandler(AuthenticationFailureHandler failureHandler) {
|
||||||
|
this.failureHandler = failureHandler;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set exclude url patterns.
|
||||||
|
*
|
||||||
|
* @param excludeUrls exclude urls
|
||||||
|
*/
|
||||||
|
public AdminAuthenticationFilter setExcludeUrlPatterns(String... excludeUrls) {
|
||||||
|
this.excludeUrlPatterns = excludeUrls == null ? Collections.emptyList() : Collections.unmodifiableCollection(Arrays.asList(excludeUrls));
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package cc.ryanc.halo.security.handler;
|
package cc.ryanc.halo.security.handler;
|
||||||
|
|
||||||
import cc.ryanc.halo.exception.HaloException;
|
import cc.ryanc.halo.exception.HaloException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
@ -15,10 +14,6 @@ import java.io.IOException;
|
||||||
*/
|
*/
|
||||||
public class AdminAuthenticationFailureHandler extends DefaultAuthenticationFailureHandler {
|
public class AdminAuthenticationFailureHandler extends DefaultAuthenticationFailureHandler {
|
||||||
|
|
||||||
public AdminAuthenticationFailureHandler(boolean productionEnv, ObjectMapper objectMapper) {
|
|
||||||
super(productionEnv, objectMapper);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(HttpServletRequest request, HttpServletResponse response, HaloException exception) throws IOException, ServletException {
|
public void onFailure(HttpServletRequest request, HttpServletResponse response, HaloException exception) throws IOException, ServletException {
|
||||||
// TODO handler the admin authentication failure.
|
// TODO handler the admin authentication failure.
|
||||||
|
|
|
@ -3,10 +3,12 @@ package cc.ryanc.halo.security.handler;
|
||||||
import cc.ryanc.halo.exception.HaloException;
|
import cc.ryanc.halo.exception.HaloException;
|
||||||
import cc.ryanc.halo.model.support.BaseResponse;
|
import cc.ryanc.halo.model.support.BaseResponse;
|
||||||
import cc.ryanc.halo.utils.ExceptionUtils;
|
import cc.ryanc.halo.utils.ExceptionUtils;
|
||||||
|
import cc.ryanc.halo.utils.JsonUtils;
|
||||||
import cn.hutool.extra.servlet.ServletUtil;
|
import cn.hutool.extra.servlet.ServletUtil;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
@ -22,14 +24,11 @@ import java.io.IOException;
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandler {
|
public class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandler {
|
||||||
|
|
||||||
private final boolean productionEnv;
|
private boolean productionEnv = true;
|
||||||
|
|
||||||
private final ObjectMapper objectMapper;
|
private ObjectMapper objectMapper = JsonUtils.DEFAULT_JSON_MAPPER;
|
||||||
|
|
||||||
public DefaultAuthenticationFailureHandler(boolean productionEnv,
|
public DefaultAuthenticationFailureHandler() {
|
||||||
ObjectMapper objectMapper) {
|
|
||||||
this.productionEnv = productionEnv;
|
|
||||||
this.objectMapper = objectMapper;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -52,4 +51,21 @@ public class DefaultAuthenticationFailureHandler implements AuthenticationFailur
|
||||||
response.getWriter().write(objectMapper.writeValueAsString(errorDetail));
|
response.getWriter().write(objectMapper.writeValueAsString(errorDetail));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets custom object mapper.
|
||||||
|
*
|
||||||
|
* @param objectMapper object mapper
|
||||||
|
* @return current authentication failure handler
|
||||||
|
*/
|
||||||
|
public DefaultAuthenticationFailureHandler setObjectMapper(ObjectMapper objectMapper) {
|
||||||
|
Assert.notNull(objectMapper, "Object mapper must not be null");
|
||||||
|
|
||||||
|
this.objectMapper = objectMapper;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultAuthenticationFailureHandler setProductionEnv(boolean productionEnv) {
|
||||||
|
this.productionEnv = productionEnv;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@ import cc.ryanc.halo.model.vo.CommentListVO;
|
||||||
import cc.ryanc.halo.model.vo.CommentVO;
|
import cc.ryanc.halo.model.vo.CommentVO;
|
||||||
import cc.ryanc.halo.repository.CommentRepository;
|
import cc.ryanc.halo.repository.CommentRepository;
|
||||||
import cc.ryanc.halo.repository.PostRepository;
|
import cc.ryanc.halo.repository.PostRepository;
|
||||||
|
import cc.ryanc.halo.security.authentication.Authentication;
|
||||||
|
import cc.ryanc.halo.security.context.SecurityContextHolder;
|
||||||
import cc.ryanc.halo.service.CommentService;
|
import cc.ryanc.halo.service.CommentService;
|
||||||
import cc.ryanc.halo.service.OptionService;
|
import cc.ryanc.halo.service.OptionService;
|
||||||
import cc.ryanc.halo.service.base.AbstractCrudService;
|
import cc.ryanc.halo.service.base.AbstractCrudService;
|
||||||
|
@ -110,7 +112,12 @@ public class CommentServiceImpl extends AbstractCrudService<Comment, Long> imple
|
||||||
comment.setIpAddress(ServletUtil.getClientIP(request));
|
comment.setIpAddress(ServletUtil.getClientIP(request));
|
||||||
comment.setUserAgent(ServletUtil.getHeaderIgnoreCase(request, HttpHeaders.USER_AGENT));
|
comment.setUserAgent(ServletUtil.getHeaderIgnoreCase(request, HttpHeaders.USER_AGENT));
|
||||||
// TODO Check user login status and set this field
|
// TODO Check user login status and set this field
|
||||||
comment.setIsAdmin(false);
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
if (authentication != null) {
|
||||||
|
// If the user is login
|
||||||
|
comment.setIsAdmin(true);
|
||||||
|
}
|
||||||
|
|
||||||
comment.setAuthor(HtmlUtils.htmlEscape(comment.getAuthor()));
|
comment.setAuthor(HtmlUtils.htmlEscape(comment.getAuthor()));
|
||||||
comment.setGavatarMd5(SecureUtil.md5(comment.getEmail()));
|
comment.setGavatarMd5(SecureUtil.md5(comment.getEmail()));
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,17 @@ package cc.ryanc.halo.web.controller.admin.api;
|
||||||
|
|
||||||
import cc.ryanc.halo.model.dto.CommentOutputDTO;
|
import cc.ryanc.halo.model.dto.CommentOutputDTO;
|
||||||
import cc.ryanc.halo.model.entity.Comment;
|
import cc.ryanc.halo.model.entity.Comment;
|
||||||
|
import cc.ryanc.halo.model.entity.User;
|
||||||
|
import cc.ryanc.halo.model.enums.BlogProperties;
|
||||||
import cc.ryanc.halo.model.enums.CommentStatus;
|
import cc.ryanc.halo.model.enums.CommentStatus;
|
||||||
import cc.ryanc.halo.model.params.CommentParam;
|
import cc.ryanc.halo.model.params.CommentParam;
|
||||||
import cc.ryanc.halo.model.vo.CommentListVO;
|
import cc.ryanc.halo.model.vo.CommentListVO;
|
||||||
|
import cc.ryanc.halo.security.authentication.Authentication;
|
||||||
|
import cc.ryanc.halo.security.context.SecurityContextHolder;
|
||||||
import cc.ryanc.halo.service.CommentService;
|
import cc.ryanc.halo.service.CommentService;
|
||||||
import cc.ryanc.halo.service.OptionService;
|
import cc.ryanc.halo.service.OptionService;
|
||||||
import cc.ryanc.halo.service.PostService;
|
import cc.ryanc.halo.service.PostService;
|
||||||
|
import cc.ryanc.halo.utils.ValidationUtils;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
|
@ -58,6 +63,19 @@ public class CommentController {
|
||||||
|
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public CommentOutputDTO createBy(@Valid @RequestBody CommentParam commentParam, HttpServletRequest request) {
|
public CommentOutputDTO createBy(@Valid @RequestBody CommentParam commentParam, HttpServletRequest request) {
|
||||||
|
// Get authentication
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
if (authentication != null) {
|
||||||
|
User user = authentication.getDetail().getUser();
|
||||||
|
// If the admin is login
|
||||||
|
commentParam.setAuthor(user.getNickname());
|
||||||
|
commentParam.setEmail(user.getEmail());
|
||||||
|
commentParam.setAuthor(optionService.getByPropertyOfNullable(BlogProperties.BLOG_URL));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the comment param manually
|
||||||
|
ValidationUtils.validate(commentParam);
|
||||||
|
|
||||||
// Check post id
|
// Check post id
|
||||||
postService.mustExistById(commentParam.getPostId());
|
postService.mustExistById(commentParam.getPostId());
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue