diff --git a/src/main/java/run/halo/app/config/WebSecurityConfig.java b/src/main/java/run/halo/app/config/WebSecurityConfig.java index 014605097..3b80726c3 100644 --- a/src/main/java/run/halo/app/config/WebSecurityConfig.java +++ b/src/main/java/run/halo/app/config/WebSecurityConfig.java @@ -6,12 +6,14 @@ import com.nimbusds.jose.jwk.RSAKey; import com.nimbusds.jose.jwk.source.ImmutableJWKSet; import com.nimbusds.jose.jwk.source.JWKSource; import com.nimbusds.jose.proc.SecurityContext; +import jakarta.servlet.http.HttpServletRequest; import java.io.IOException; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.AuthenticationManagerResolver; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -29,6 +31,7 @@ import org.springframework.security.oauth2.jwt.NimbusJwtEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import org.springframework.security.web.context.SecurityContextPersistenceFilter; import run.halo.app.identity.authentication.InMemoryOAuth2AuthorizationService; import run.halo.app.identity.authentication.JwtGenerator; @@ -38,6 +41,8 @@ import run.halo.app.identity.authentication.OAuth2RefreshTokenAuthenticationProv import run.halo.app.identity.authentication.OAuth2TokenEndpointFilter; import run.halo.app.identity.authentication.ProviderContextFilter; import run.halo.app.identity.authentication.ProviderSettings; +import run.halo.app.identity.authentication.verifier.BearerTokenAuthenticationFilter; +import run.halo.app.identity.authentication.verifier.JwtProvidedDecoderAuthenticationManagerResolver; import run.halo.app.identity.entrypoint.JwtAccessDeniedHandler; import run.halo.app.identity.entrypoint.JwtAuthenticationEntryPoint; import run.halo.app.infra.properties.JwtProperties; @@ -77,6 +82,8 @@ public class WebSecurityConfig { .addFilterBefore(new OAuth2TokenEndpointFilter(authenticationManager(), providerSettings.getTokenEndpoint()), FilterSecurityInterceptor.class) + .addFilterBefore(new BearerTokenAuthenticationFilter(authenticationManagerResolver()), + BasicAuthenticationFilter.class) .addFilterAfter(providerContextFilter, SecurityContextPersistenceFilter.class) .sessionManagement( (session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) @@ -87,6 +94,10 @@ public class WebSecurityConfig { return http.build(); } + AuthenticationManagerResolver authenticationManagerResolver() { + return new JwtProvidedDecoderAuthenticationManagerResolver(jwtDecoder()); + } + @Bean AuthenticationManager authenticationManager() throws Exception { authenticationManagerBuilder.authenticationProvider(passwordAuthenticationProvider()) diff --git a/src/main/java/run/halo/app/identity/HelloController.java b/src/main/java/run/halo/app/identity/HelloController.java new file mode 100644 index 000000000..6acb98a86 --- /dev/null +++ b/src/main/java/run/halo/app/identity/HelloController.java @@ -0,0 +1,21 @@ +package run.halo.app.identity; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * A controller should ONLY be used during testing for this PR. + * + * @author guqing + * @since 2.0.0 + */ +@RestController +@RequestMapping("/tests") +public class HelloController { + + @GetMapping + public String hello() { + return "Now you see me."; + } +} diff --git a/src/main/java/run/halo/app/identity/authentication/verifier/JwtProvidedDecoderAuthenticationManagerResolver.java b/src/main/java/run/halo/app/identity/authentication/verifier/JwtProvidedDecoderAuthenticationManagerResolver.java new file mode 100644 index 000000000..82abdddc0 --- /dev/null +++ b/src/main/java/run/halo/app/identity/authentication/verifier/JwtProvidedDecoderAuthenticationManagerResolver.java @@ -0,0 +1,25 @@ +package run.halo.app.identity.authentication.verifier; + +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.AuthenticationManagerResolver; +import org.springframework.security.oauth2.jwt.JwtDecoder; +import org.springframework.util.Assert; + +/** + * A jwt resolver for {@link AuthenticationManager} use {@link JwtDecoder}. + * + * @author guqing + * @since 2.0.0 + */ +public record JwtProvidedDecoderAuthenticationManagerResolver(JwtDecoder jwtDecoder) + implements AuthenticationManagerResolver { + public JwtProvidedDecoderAuthenticationManagerResolver { + Assert.notNull(jwtDecoder, "jwtDecoder cannot be null"); + } + + @Override + public AuthenticationManager resolve(HttpServletRequest request) { + return new JwtAuthenticationProvider(jwtDecoder)::authenticate; + } +}