mirror of https://github.com/halo-dev/halo
Redirect to user center if authenticated users access login and signup pages (#6740)
#### What type of PR is this? /kind improvement /area core /milestone 2.20.x #### What this PR does / why we need it: This PR make authenticated users redirect to user center if they are trying to access login and signup pages. #### Special notes for your reviewer: 1. Log in Halo 2. Try to request <http://localhost:8090/login> or <http://localhost:8090/signup>. #### Does this PR introduce a user-facing change? ```release-note None ```pull/6749/head
parent
e11a494c96
commit
462fac0eb6
|
@ -44,6 +44,7 @@ import run.halo.app.security.authentication.impl.RsaKeyService;
|
|||
import run.halo.app.security.authentication.pat.PatAuthenticationManager;
|
||||
import run.halo.app.security.authentication.pat.PatServerWebExchangeMatcher;
|
||||
import run.halo.app.security.authorization.AuthorityUtils;
|
||||
import run.halo.app.security.authorization.NotAuthenticatedAuthorizationManager;
|
||||
import run.halo.app.security.authorization.RequestInfoAuthorizationManager;
|
||||
import run.halo.app.security.session.InMemoryReactiveIndexedSessionRepository;
|
||||
import run.halo.app.security.session.ReactiveIndexedSessionRepository;
|
||||
|
@ -90,6 +91,8 @@ public class WebServerSecurityConfig {
|
|||
"/apis/**",
|
||||
"/actuator/**"
|
||||
).access(new RequestInfoAuthorizationManager(roleService))
|
||||
.pathMatchers(HttpMethod.GET, "/login", "/signup")
|
||||
.access(new NotAuthenticatedAuthorizationManager())
|
||||
.pathMatchers(
|
||||
"/login/**",
|
||||
"/challenges/**",
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package run.halo.app.security;
|
||||
|
||||
import static org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers.anyExchange;
|
||||
import static org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers.pathMatchers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.config.web.server.ServerHttpSecurity;
|
||||
import org.springframework.security.oauth2.server.resource.web.access.server.BearerTokenServerAccessDeniedHandler;
|
||||
|
@ -11,8 +15,6 @@ import org.springframework.security.web.server.authentication.AuthenticationConv
|
|||
import org.springframework.security.web.server.authorization.HttpStatusServerAccessDeniedHandler;
|
||||
import org.springframework.security.web.server.authorization.ServerWebExchangeDelegatingServerAccessDeniedHandler;
|
||||
import org.springframework.security.web.server.savedrequest.ServerRequestCache;
|
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
|
||||
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import run.halo.app.security.authentication.SecurityConfigurer;
|
||||
|
@ -40,7 +42,7 @@ public class ExceptionSecurityConfigurer implements SecurityConfigurer {
|
|||
http.exceptionHandling(exception -> {
|
||||
var accessDeniedHandlers =
|
||||
new ArrayList<ServerWebExchangeDelegatingServerAccessDeniedHandler.DelegateEntry>(
|
||||
2
|
||||
3
|
||||
);
|
||||
accessDeniedHandlers.add(
|
||||
new ServerWebExchangeDelegatingServerAccessDeniedHandler.DelegateEntry(
|
||||
|
@ -51,19 +53,24 @@ public class ExceptionSecurityConfigurer implements SecurityConfigurer {
|
|||
));
|
||||
accessDeniedHandlers.add(
|
||||
new ServerWebExchangeDelegatingServerAccessDeniedHandler.DelegateEntry(
|
||||
ServerWebExchangeMatchers.anyExchange(),
|
||||
pathMatchers(HttpMethod.GET, "/login", "/signup"),
|
||||
new RedirectAccessDeniedHandler("/uc")
|
||||
));
|
||||
accessDeniedHandlers.add(
|
||||
new ServerWebExchangeDelegatingServerAccessDeniedHandler.DelegateEntry(
|
||||
anyExchange(),
|
||||
new HttpStatusServerAccessDeniedHandler(HttpStatus.FORBIDDEN)
|
||||
)
|
||||
);
|
||||
|
||||
var entryPoints =
|
||||
new ArrayList<DelegatingServerAuthenticationEntryPoint.DelegateEntry>(3);
|
||||
new ArrayList<DelegatingServerAuthenticationEntryPoint.DelegateEntry>(2);
|
||||
entryPoints.add(new DelegatingServerAuthenticationEntryPoint.DelegateEntry(
|
||||
TwoFactorAuthenticationEntryPoint.MATCHER,
|
||||
new TwoFactorAuthenticationEntryPoint(messageSource, context)
|
||||
));
|
||||
entryPoints.add(new DelegatingServerAuthenticationEntryPoint.DelegateEntry(
|
||||
exchange -> ServerWebExchangeMatcher.MatchResult.match(),
|
||||
anyExchange(),
|
||||
new DefaultServerAuthenticationEntryPoint(serverRequestCache)
|
||||
));
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
package run.halo.app.security;
|
||||
|
||||
import java.net.URI;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.web.server.DefaultServerRedirectStrategy;
|
||||
import org.springframework.security.web.server.ServerRedirectStrategy;
|
||||
import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Redirect access denied handler.
|
||||
*
|
||||
* @author johnniang
|
||||
* @since 2.20.0
|
||||
*/
|
||||
public class RedirectAccessDeniedHandler implements ServerAccessDeniedHandler {
|
||||
|
||||
private final ServerRedirectStrategy redirectStrategy = new DefaultServerRedirectStrategy();
|
||||
|
||||
private final URI redirectUri;
|
||||
|
||||
public RedirectAccessDeniedHandler(String redirectUri) {
|
||||
this.redirectUri = URI.create(redirectUri);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException denied) {
|
||||
return redirectStrategy.sendRedirect(exchange, redirectUri);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package run.halo.app.security.authorization;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.authorization.ReactiveAuthorizationManager;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.server.authorization.AuthorizationContext;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Authorization manager that checks if the user is not authenticated.
|
||||
*
|
||||
* @author johnniang
|
||||
* @since 2.20.0
|
||||
*/
|
||||
public class NotAuthenticatedAuthorizationManager
|
||||
implements ReactiveAuthorizationManager<AuthorizationContext> {
|
||||
|
||||
private final AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
||||
|
||||
@Override
|
||||
public Mono<AuthorizationDecision> check(Mono<Authentication> authentication,
|
||||
AuthorizationContext object) {
|
||||
return authentication.map(a -> !trustResolver.isAuthenticated(a))
|
||||
.defaultIfEmpty(true)
|
||||
.map(AuthorizationDecision::new);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue