mirror of https://github.com/halo-dev/halo
Complete api authentication
parent
574ae54208
commit
f7d16e06a3
|
@ -102,8 +102,10 @@ public class HaloConfiguration {
|
|||
}
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean<ApiAuthenticationFilter> apiAuthenticationFilter(HaloProperties haloProperties, ObjectMapper objectMapper) {
|
||||
ApiAuthenticationFilter apiFilter = new ApiAuthenticationFilter(haloProperties);
|
||||
public FilterRegistrationBean<ApiAuthenticationFilter> apiAuthenticationFilter(HaloProperties haloProperties,
|
||||
ObjectMapper objectMapper,
|
||||
OptionService optionService) {
|
||||
ApiAuthenticationFilter apiFilter = new ApiAuthenticationFilter(haloProperties, optionService);
|
||||
|
||||
DefaultAuthenticationFailureHandler failureHandler = new DefaultAuthenticationFailureHandler();
|
||||
failureHandler.setProductionEnv(haloProperties.isProductionEnv());
|
||||
|
|
|
@ -8,13 +8,13 @@ import org.springframework.context.annotation.Configuration;
|
|||
import org.springframework.core.Ordered;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import run.halo.app.config.properties.HaloProperties;
|
||||
import run.halo.app.model.entity.User;
|
||||
import run.halo.app.security.filter.AdminAuthenticationFilter;
|
||||
import run.halo.app.security.filter.ApiAuthenticationFilter;
|
||||
import run.halo.app.security.support.UserDetail;
|
||||
import springfox.documentation.builders.*;
|
||||
import springfox.documentation.schema.AlternateTypeRule;
|
||||
|
@ -34,7 +34,6 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
import static run.halo.app.model.support.HaloConst.HALO_VERSION;
|
||||
import static run.halo.app.model.support.HaloConst.TOKEN_HEADER;
|
||||
import static springfox.documentation.schema.AlternateTypeRules.newRule;
|
||||
|
||||
/**
|
||||
|
@ -140,8 +139,8 @@ public class SwaggerConfiguration {
|
|||
|
||||
private List<ApiKey> portalApiKeys() {
|
||||
return Arrays.asList(
|
||||
new ApiKey("Token from header", HttpHeaders.AUTHORIZATION, In.HEADER.name()),
|
||||
new ApiKey("Token from query", "token", In.QUERY.name())
|
||||
new ApiKey("Token from header", ApiAuthenticationFilter.API_TOKEN_HEADER_NAME, In.HEADER.name()),
|
||||
new ApiKey("Token from query", ApiAuthenticationFilter.API_TOKEN_QUERY_NAME, In.QUERY.name())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,11 +25,6 @@ public class HaloConst {
|
|||
*/
|
||||
public static final String HALO_VERSION = "1.0.0";
|
||||
|
||||
/**
|
||||
* Token of header param
|
||||
*/
|
||||
public static final String TOKEN_HEADER = "token";
|
||||
|
||||
/**
|
||||
* Suffix of freemarker template file
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package run.halo.app.security.filter;
|
||||
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
@ -41,6 +42,15 @@ public abstract class AbstractAuthenticationFilter extends OncePerRequestFilter
|
|||
antPathMatcher = new AntPathMatcher();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets token from request.
|
||||
*
|
||||
* @param request http servlet request must not be null
|
||||
* @return token or null
|
||||
*/
|
||||
@Nullable
|
||||
protected abstract String getTokenFromRequest(@NonNull HttpServletRequest request);
|
||||
|
||||
@Override
|
||||
protected boolean shouldNotFilter(HttpServletRequest request) {
|
||||
Assert.notNull(request, "Http servlet request must not be null");
|
||||
|
|
|
@ -137,14 +137,8 @@ public class AdminAuthenticationFilter extends AbstractAuthenticationFilter {
|
|||
getFailureHandler().onFailure(request, response, new AuthenticationException("You have to login before accessing admin api"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets token from request.
|
||||
*
|
||||
* @param request http servlet request must not be null
|
||||
* @return token or null
|
||||
*/
|
||||
@Nullable
|
||||
private String getTokenFromRequest(@NonNull HttpServletRequest request) {
|
||||
@Override
|
||||
protected String getTokenFromRequest(@NonNull HttpServletRequest request) {
|
||||
Assert.notNull(request, "Http servlet request must not be null");
|
||||
|
||||
// Get from header
|
||||
|
|
|
@ -1,33 +1,97 @@
|
|||
package run.halo.app.security.filter;
|
||||
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.util.Assert;
|
||||
import run.halo.app.config.properties.HaloProperties;
|
||||
import run.halo.app.exception.AuthenticationException;
|
||||
import run.halo.app.exception.ForbiddenException;
|
||||
import run.halo.app.model.properties.OtherProperties;
|
||||
import run.halo.app.service.OptionService;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Api authentication Filter
|
||||
*
|
||||
* @author johnniang
|
||||
*/
|
||||
@Slf4j
|
||||
public class ApiAuthenticationFilter extends AbstractAuthenticationFilter {
|
||||
|
||||
private final AntPathMatcher antPathMatcher;
|
||||
public final static String API_TOKEN_HEADER_NAME = "API-" + HttpHeaders.AUTHORIZATION;
|
||||
|
||||
public ApiAuthenticationFilter(HaloProperties haloProperties) {
|
||||
public final static String API_TOKEN_QUERY_NAME = "apiToken";
|
||||
|
||||
private final OptionService optionService;
|
||||
|
||||
public ApiAuthenticationFilter(HaloProperties haloProperties,
|
||||
OptionService optionService) {
|
||||
super(haloProperties);
|
||||
antPathMatcher = new AntPathMatcher();
|
||||
this.optionService = optionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
// TODO Handle authentication
|
||||
// Get token
|
||||
String token = getTokenFromRequest(request);
|
||||
|
||||
if (StringUtils.isBlank(token)) {
|
||||
// If the token is missing
|
||||
getFailureHandler().onFailure(request, response, new AuthenticationException("Missing API token"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Get api_enable from option
|
||||
Boolean apiEnabled = optionService.getByPropertyOrDefault(OtherProperties.API_ENABLED, Boolean.class, false);
|
||||
|
||||
if (!apiEnabled) {
|
||||
getFailureHandler().onFailure(request, response, new ForbiddenException("API has been disabled by blogger currently"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Get token from option
|
||||
Optional<String> optionalToken = optionService.getByProperty(OtherProperties.API_TOKEN, String.class);
|
||||
|
||||
if (!optionalToken.isPresent()) {
|
||||
// If the token is not set
|
||||
getFailureHandler().onFailure(request, response, new AuthenticationException("API Token hasn't been set by blogger"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!StringUtils.equals(token, optionalToken.get())) {
|
||||
// If the token is mismatch
|
||||
getFailureHandler().onFailure(request, response, new AuthenticationException("Token is mismatch"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Do filter
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTokenFromRequest(@NonNull HttpServletRequest request) {
|
||||
Assert.notNull(request, "Http servlet request must not be null");
|
||||
|
||||
// Get from header
|
||||
String token = request.getHeader(API_TOKEN_HEADER_NAME);
|
||||
|
||||
// Get from param
|
||||
if (StringUtils.isBlank(token)) {
|
||||
token = request.getParameter(API_TOKEN_QUERY_NAME);
|
||||
|
||||
log.debug("Got token from parameter: [{}: {}]", API_TOKEN_QUERY_NAME, token);
|
||||
} else {
|
||||
log.debug("Got token from header: [{}: {}]", API_TOKEN_HEADER_NAME, token);
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue