43
43
import org .springframework .security .authorization .AuthorityReactiveAuthorizationManager ;
44
44
import org .springframework .security .authorization .AuthorizationDecision ;
45
45
import org .springframework .security .authorization .ReactiveAuthorizationManager ;
46
+ import org .springframework .security .core .Authentication ;
46
47
import org .springframework .security .core .AuthenticationException ;
47
48
import org .springframework .security .oauth2 .client .InMemoryReactiveOAuth2AuthorizedClientService ;
48
49
import org .springframework .security .oauth2 .client .ReactiveOAuth2AuthorizedClientService ;
114
115
import org .springframework .security .web .server .savedrequest .WebSessionServerRequestCache ;
115
116
import org .springframework .security .web .server .ui .LoginPageGeneratingWebFilter ;
116
117
import org .springframework .security .web .server .ui .LogoutPageGeneratingWebFilter ;
118
+ import org .springframework .security .web .server .util .matcher .AndServerWebExchangeMatcher ;
117
119
import org .springframework .security .web .server .util .matcher .MediaTypeServerWebExchangeMatcher ;
120
+ import org .springframework .security .web .server .util .matcher .NegatedServerWebExchangeMatcher ;
118
121
import org .springframework .security .web .server .util .matcher .PathPatternParserServerWebExchangeMatcher ;
119
122
import org .springframework .security .web .server .util .matcher .ServerWebExchangeMatcher ;
120
123
import org .springframework .security .web .server .util .matcher .ServerWebExchangeMatcherEntry ;
130
133
import org .springframework .web .server .WebFilterChain ;
131
134
132
135
import static org .springframework .security .web .server .DelegatingServerAuthenticationEntryPoint .DelegateEntry ;
136
+ import static org .springframework .security .web .server .util .matcher .ServerWebExchangeMatcher .MatchResult .match ;
137
+ import static org .springframework .security .web .server .util .matcher .ServerWebExchangeMatcher .MatchResult .notMatch ;
133
138
134
139
/**
135
140
* A {@link ServerHttpSecurity} is similar to Spring Security's {@code HttpSecurity} but for WebFlux.
@@ -703,6 +708,9 @@ protected void configure(ServerHttpSecurity http) {
703
708
public class JwtSpec {
704
709
private ReactiveJwtDecoder jwtDecoder ;
705
710
711
+ private BearerTokenServerWebExchangeMatcher bearerTokenServerWebExchangeMatcher =
712
+ new BearerTokenServerWebExchangeMatcher ();
713
+
706
714
/**
707
715
* Configures the {@link ReactiveJwtDecoder} to use
708
716
* @param jwtDecoder the decoder to use
@@ -740,13 +748,20 @@ public OAuth2ResourceServerSpec and() {
740
748
}
741
749
742
750
protected void configure (ServerHttpSecurity http ) {
751
+ ServerBearerTokenAuthenticationConverter bearerTokenConverter =
752
+ new ServerBearerTokenAuthenticationConverter ();
753
+ this .bearerTokenServerWebExchangeMatcher .setBearerTokenConverter (bearerTokenConverter );
754
+
755
+ registerDefaultCsrfOverride (http );
756
+
743
757
BearerTokenServerAuthenticationEntryPoint entryPoint = new BearerTokenServerAuthenticationEntryPoint ();
744
758
ReactiveJwtDecoder jwtDecoder = getJwtDecoder ();
745
759
JwtReactiveAuthenticationManager authenticationManager = new JwtReactiveAuthenticationManager (
746
760
jwtDecoder );
747
761
AuthenticationWebFilter oauth2 = new AuthenticationWebFilter (authenticationManager );
748
- oauth2 .setServerAuthenticationConverter (new ServerBearerTokenAuthenticationConverter () );
762
+ oauth2 .setServerAuthenticationConverter (bearerTokenConverter );
749
763
oauth2 .setAuthenticationFailureHandler (new ServerAuthenticationEntryPointFailureHandler (entryPoint ));
764
+
750
765
http
751
766
.exceptionHandling ()
752
767
.authenticationEntryPoint (entryPoint )
@@ -760,6 +775,38 @@ protected ReactiveJwtDecoder getJwtDecoder() {
760
775
}
761
776
return this .jwtDecoder ;
762
777
}
778
+
779
+ private void registerDefaultCsrfOverride (ServerHttpSecurity http ) {
780
+ if ( http .csrf != null && !http .csrf .specifiedRequireCsrfProtectionMatcher ) {
781
+ http
782
+ .csrf ()
783
+ .requireCsrfProtectionMatcher (
784
+ new AndServerWebExchangeMatcher (
785
+ CsrfWebFilter .DEFAULT_CSRF_MATCHER ,
786
+ new NegatedServerWebExchangeMatcher (
787
+ this .bearerTokenServerWebExchangeMatcher )));
788
+ }
789
+ }
790
+
791
+ private class BearerTokenServerWebExchangeMatcher implements ServerWebExchangeMatcher {
792
+ ServerBearerTokenAuthenticationConverter bearerTokenConverter ;
793
+
794
+ @ Override
795
+ public Mono <MatchResult > matches (ServerWebExchange exchange ) {
796
+ return this .bearerTokenConverter .convert (exchange )
797
+ .flatMap (this ::nullAuthentication )
798
+ .onErrorResume (e -> notMatch ());
799
+ }
800
+
801
+ public void setBearerTokenConverter (ServerBearerTokenAuthenticationConverter bearerTokenConverter ) {
802
+ Assert .notNull (bearerTokenConverter , "bearerTokenConverter cannot be null" );
803
+ this .bearerTokenConverter = bearerTokenConverter ;
804
+ }
805
+
806
+ private Mono <MatchResult > nullAuthentication (Authentication authentication ) {
807
+ return authentication == null ? notMatch () : match ();
808
+ }
809
+ }
763
810
}
764
811
765
812
public ServerHttpSecurity and () {
@@ -1173,6 +1220,8 @@ public AuthorizeExchangeSpec access(ReactiveAuthorizationManager<AuthorizationCo
1173
1220
public class CsrfSpec {
1174
1221
private CsrfWebFilter filter = new CsrfWebFilter ();
1175
1222
1223
+ private boolean specifiedRequireCsrfProtectionMatcher ;
1224
+
1176
1225
/**
1177
1226
* Configures the {@link ServerAccessDeniedHandler} used when a CSRF token is invalid. Default is
1178
1227
* to send an {@link org.springframework.http.HttpStatus#FORBIDDEN}.
@@ -1209,6 +1258,7 @@ public CsrfSpec csrfTokenRepository(
1209
1258
public CsrfSpec requireCsrfProtectionMatcher (
1210
1259
ServerWebExchangeMatcher requireCsrfProtectionMatcher ) {
1211
1260
this .filter .setRequireCsrfProtectionMatcher (requireCsrfProtectionMatcher );
1261
+ this .specifiedRequireCsrfProtectionMatcher = true ;
1212
1262
return this ;
1213
1263
}
1214
1264
0 commit comments