feat: Add bearer token filter config for authentication (#1876)

pull/1878/head
guqing 2022-04-22 15:36:11 +08:00 committed by GitHub
parent 6de85184b1
commit a7b9433120
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 0 deletions

View File

@ -6,12 +6,14 @@ import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet; import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource; import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext; import com.nimbusds.jose.proc.SecurityContext;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException; import java.io.IOException;
import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey; import java.security.interfaces.RSAPublicKey;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationManagerResolver;
import org.springframework.security.config.Customizer; import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 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.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.context.SecurityContextPersistenceFilter; import org.springframework.security.web.context.SecurityContextPersistenceFilter;
import run.halo.app.identity.authentication.InMemoryOAuth2AuthorizationService; import run.halo.app.identity.authentication.InMemoryOAuth2AuthorizationService;
import run.halo.app.identity.authentication.JwtGenerator; 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.OAuth2TokenEndpointFilter;
import run.halo.app.identity.authentication.ProviderContextFilter; import run.halo.app.identity.authentication.ProviderContextFilter;
import run.halo.app.identity.authentication.ProviderSettings; 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.JwtAccessDeniedHandler;
import run.halo.app.identity.entrypoint.JwtAuthenticationEntryPoint; import run.halo.app.identity.entrypoint.JwtAuthenticationEntryPoint;
import run.halo.app.infra.properties.JwtProperties; import run.halo.app.infra.properties.JwtProperties;
@ -77,6 +82,8 @@ public class WebSecurityConfig {
.addFilterBefore(new OAuth2TokenEndpointFilter(authenticationManager(), .addFilterBefore(new OAuth2TokenEndpointFilter(authenticationManager(),
providerSettings.getTokenEndpoint()), providerSettings.getTokenEndpoint()),
FilterSecurityInterceptor.class) FilterSecurityInterceptor.class)
.addFilterBefore(new BearerTokenAuthenticationFilter(authenticationManagerResolver()),
BasicAuthenticationFilter.class)
.addFilterAfter(providerContextFilter, SecurityContextPersistenceFilter.class) .addFilterAfter(providerContextFilter, SecurityContextPersistenceFilter.class)
.sessionManagement( .sessionManagement(
(session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) (session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
@ -87,6 +94,10 @@ public class WebSecurityConfig {
return http.build(); return http.build();
} }
AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver() {
return new JwtProvidedDecoderAuthenticationManagerResolver(jwtDecoder());
}
@Bean @Bean
AuthenticationManager authenticationManager() throws Exception { AuthenticationManager authenticationManager() throws Exception {
authenticationManagerBuilder.authenticationProvider(passwordAuthenticationProvider()) authenticationManagerBuilder.authenticationProvider(passwordAuthenticationProvider())

View File

@ -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.";
}
}

View File

@ -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<HttpServletRequest> {
public JwtProvidedDecoderAuthenticationManagerResolver {
Assert.notNull(jwtDecoder, "jwtDecoder cannot be null");
}
@Override
public AuthenticationManager resolve(HttpServletRequest request) {
return new JwtAuthenticationProvider(jwtDecoder)::authenticate;
}
}