授權 ServerHttpRequest

Spring Security 提供對傳入 HTTP 請求進行授權的支援。預設情況下,Spring Security 的授權將要求所有請求都經過認證。明確的配置如下所示:

所有請求都需要經過認證的使用者
  • Java

  • Kotlin

@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
    http
        .authorizeExchange(exchanges -> exchanges
            .anyExchange().authenticated()
        )
        .httpBasic(withDefaults())
        .formLogin(withDefaults());
    return http.build();
}
@Bean
fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
    return http {
        authorizeExchange {
            authorize(anyExchange, authenticated)
        }
        formLogin { }
        httpBasic { }
    }
}

我們可以透過按優先順序順序新增更多規則來配置 Spring Security,使其具有不同的規則。

多個授權請求規則
  • Java

  • Kotlin

import static org.springframework.security.authorization.AuthorityReactiveAuthorizationManager.hasRole;
// ...
@Bean
SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) {
	http
		// ...
		.authorizeExchange((authorize) -> authorize                          (1)
			.pathMatchers("/resources/**", "/signup", "/about").permitAll()  (2)
			.pathMatchers("/admin/**").hasRole("ADMIN")                      (3)
			.pathMatchers("/db/**").access((authentication, context) ->      (4)
				hasRole("ADMIN").check(authentication, context)
					.filter(decision -> !decision.isGranted())
					.switchIfEmpty(hasRole("DBA").check(authentication, context))
			)
			.anyExchange().denyAll()                                         (5)
		);
	return http.build();
}
@Bean
fun springSecurityFilterChain(http: ServerHttpSecurity): SecurityWebFilterChain {
    return http {
        authorizeExchange {                                                           (1)
            authorize(pathMatchers("/resources/**", "/signup", "/about"), permitAll)  (2)
            authorize("/admin/**", hasRole("ADMIN"))                                  (3)
            authorize("/db/**", { authentication, context ->                          (4)
                hasRole("ADMIN").check(authentication, context)
                    .filter({ decision -> !decision.isGranted() })
                    .switchIfEmpty(hasRole("DBA").check(authentication, context))
            })
            authorize(anyExchange, denyAll)                                           (5)
        }
        // ...
    }
}
1 指定了多個授權規則。每個規則都按照宣告的順序進行考慮。
2 我們指定了多個任何使用者都可以訪問的 URL 模式。具體來說,如果 URL 以 "/resources/" 開頭、等於 "/signup" 或等於 "/about",則任何使用者都可以訪問該請求。
3 任何以 "/admin/" 開頭的 URL 都將限制為具有 "ROLE_ADMIN" 許可權的使用者。您會注意到,由於我們呼叫的是 hasRole 方法,因此不需要指定 "ROLE_" 字首。
4 任何以 "/db/" 開頭的 URL 都要求使用者同時具有 "ROLE_ADMIN" 和 "ROLE_DBA"。這展示了提供自定義 ReactiveAuthorizationManager 的靈活性,使我們能夠實現任意授權邏輯。為簡單起見,示例使用 lambda 並委託給現有的 AuthorityReactiveAuthorizationManager.hasRole 實現。然而,在實際應用中,應用程式可能會在實現 ReactiveAuthorizationManager 的適當類中實現邏輯。
5 任何尚未匹配的 URL 都將被拒絕訪問。如果您不想意外忘記更新授權規則,這是一個很好的策略。