forked from halo-dev/halo
-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request halo-dev#4737 from JohnNiang/feat/mfa
Support TOTP two-factor authentication
- Loading branch information
Showing
66 changed files
with
3,083 additions
and
596 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 0 additions & 46 deletions
46
application/src/main/java/run/halo/app/core/extension/service/DefaultRoleBindingService.java
This file was deleted.
Oops, something went wrong.
16 changes: 0 additions & 16 deletions
16
application/src/main/java/run/halo/app/core/extension/service/RoleBindingService.java
This file was deleted.
Oops, something went wrong.
63 changes: 63 additions & 0 deletions
63
application/src/main/java/run/halo/app/infra/exception/RequestBodyValidationException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
package run.halo.app.infra.exception; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Locale; | ||
import org.springframework.context.MessageSource; | ||
import org.springframework.context.MessageSourceResolvable; | ||
import org.springframework.http.ProblemDetail; | ||
import org.springframework.lang.Nullable; | ||
import org.springframework.validation.BindingResult; | ||
import org.springframework.web.server.ServerWebInputException; | ||
import org.springframework.web.util.BindErrorUtils; | ||
|
||
public class RequestBodyValidationException extends ServerWebInputException { | ||
|
||
private final BindingResult bindingResult; | ||
|
||
public RequestBodyValidationException(BindingResult bindingResult) { | ||
super("Validation failure", null, null, null, null); | ||
this.bindingResult = bindingResult; | ||
} | ||
|
||
@Override | ||
public ProblemDetail updateAndGetBody(MessageSource messageSource, Locale locale) { | ||
var detail = super.updateAndGetBody(messageSource, locale); | ||
detail.setProperty("errors", collectAllErrors(messageSource, locale)); | ||
return detail; | ||
} | ||
|
||
private List<String> collectAllErrors(MessageSource messageSource, Locale locale) { | ||
var globalErrors = resolveErrors(bindingResult.getGlobalErrors(), messageSource, locale); | ||
var fieldErrors = resolveErrors(bindingResult.getFieldErrors(), messageSource, locale); | ||
var errors = new ArrayList<String>(globalErrors.size() + fieldErrors.size()); | ||
errors.addAll(globalErrors); | ||
errors.addAll(fieldErrors); | ||
return errors; | ||
} | ||
|
||
@Override | ||
public Object[] getDetailMessageArguments(MessageSource messageSource, Locale locale) { | ||
return new Object[] { | ||
resolveErrors(bindingResult.getGlobalErrors(), messageSource, locale), | ||
resolveErrors(bindingResult.getFieldErrors(), messageSource, locale) | ||
}; | ||
} | ||
|
||
@Override | ||
public Object[] getDetailMessageArguments() { | ||
return new Object[] { | ||
resolveErrors(bindingResult.getGlobalErrors(), null, Locale.getDefault()), | ||
resolveErrors(bindingResult.getFieldErrors(), null, Locale.getDefault()) | ||
}; | ||
} | ||
|
||
private static List<String> resolveErrors( | ||
List<? extends MessageSourceResolvable> errors, | ||
@Nullable MessageSource messageSource, | ||
Locale locale) { | ||
return messageSource == null | ||
? BindErrorUtils.resolve(errors).values().stream().toList() | ||
: BindErrorUtils.resolve(errors, messageSource, locale).values().stream().toList(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
application/src/main/java/run/halo/app/security/ExceptionSecurityConfigurer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package run.halo.app.security; | ||
|
||
import org.springframework.security.config.web.server.ServerHttpSecurity; | ||
import org.springframework.security.oauth2.server.resource.web.access.server.BearerTokenServerAccessDeniedHandler; | ||
import org.springframework.stereotype.Component; | ||
import run.halo.app.security.authentication.SecurityConfigurer; | ||
|
||
@Component | ||
public class ExceptionSecurityConfigurer implements SecurityConfigurer { | ||
|
||
@Override | ||
public void configure(ServerHttpSecurity http) { | ||
http.exceptionHandling(exception -> { | ||
var accessDeniedHandler = new BearerTokenServerAccessDeniedHandler(); | ||
var entryPoint = new DefaultServerAuthenticationEntryPoint(); | ||
exception | ||
.authenticationEntryPoint(entryPoint) | ||
.accessDeniedHandler(accessDeniedHandler); | ||
}); | ||
} | ||
|
||
} |
52 changes: 52 additions & 0 deletions
52
application/src/main/java/run/halo/app/security/LogoutSecurityConfigurer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package run.halo.app.security; | ||
|
||
import static org.springframework.security.config.web.server.SecurityWebFiltersOrder.LOGOUT_PAGE_GENERATING; | ||
import static run.halo.app.security.authentication.WebExchangeMatchers.ignoringMediaTypeAll; | ||
|
||
import java.net.URI; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.security.config.web.server.ServerHttpSecurity; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.web.server.WebFilterExchange; | ||
import org.springframework.security.web.server.authentication.logout.RedirectServerLogoutSuccessHandler; | ||
import org.springframework.security.web.server.authentication.logout.ServerLogoutSuccessHandler; | ||
import org.springframework.security.web.server.ui.LogoutPageGeneratingWebFilter; | ||
import org.springframework.stereotype.Component; | ||
import reactor.core.publisher.Mono; | ||
import run.halo.app.security.authentication.SecurityConfigurer; | ||
|
||
@Component | ||
public class LogoutSecurityConfigurer implements SecurityConfigurer { | ||
|
||
@Override | ||
public void configure(ServerHttpSecurity http) { | ||
http.logout(logout -> logout.logoutSuccessHandler(new LogoutSuccessHandler())); | ||
http.addFilterAt(new LogoutPageGeneratingWebFilter(), LOGOUT_PAGE_GENERATING); | ||
} | ||
|
||
public static class LogoutSuccessHandler implements ServerLogoutSuccessHandler { | ||
|
||
private final ServerLogoutSuccessHandler defaultHandler; | ||
|
||
public LogoutSuccessHandler() { | ||
var defaultHandler = new RedirectServerLogoutSuccessHandler(); | ||
defaultHandler.setLogoutSuccessUrl(URI.create("/console/?logout")); | ||
this.defaultHandler = defaultHandler; | ||
} | ||
|
||
@Override | ||
public Mono<Void> onLogoutSuccess(WebFilterExchange exchange, | ||
Authentication authentication) { | ||
return ignoringMediaTypeAll(MediaType.APPLICATION_JSON).matches(exchange.getExchange()) | ||
.flatMap(matchResult -> { | ||
if (matchResult.isMatch()) { | ||
var response = exchange.getExchange().getResponse(); | ||
response.setStatusCode(HttpStatus.NO_CONTENT); | ||
return response.setComplete(); | ||
} | ||
return defaultHandler.onLogoutSuccess(exchange, authentication); | ||
}); | ||
} | ||
} | ||
} |
Oops, something went wrong.