操作指南:在 JWT 存取權杖中新增授權 (authorities) 作為自訂宣告

本指南示範如何在 JWT 存取權杖中新增資源擁有者的授權 (authorities)。術語「authorities」可能代表不同的形式,例如角色、權限或資源擁有者的群組。

為了使資源擁有者的授權 (authorities) 可供資源伺服器使用,我們在存取權杖中新增自訂宣告。當用戶端使用存取權杖存取受保護的資源時,資源伺服器將能夠取得關於資源擁有者存取層級的資訊,以及其他潛在的用途和好處。

在 JWT 存取權杖中新增自訂宣告

您可以使用 OAuth2TokenCustomizer<JWTEncodingContext> @Bean 在存取權杖中新增您自己的自訂宣告。請注意,此 @Bean 只能定義一次,因此必須小心確保您正在自訂適當的權杖類型 — 在此情況下為存取權杖。如果您有興趣自訂 ID 權杖,請參閱 使用者資訊對應器指南 以取得更多資訊。

以下是在存取權杖中新增自訂宣告的範例 — 換句話說,授權伺服器發出的每個存取權杖都將會填入自訂宣告。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;

@Configuration
public class CustomClaimsConfiguration {
	@Bean
	public OAuth2TokenCustomizer<JwtEncodingContext> jwtTokenCustomizer() {
		return (context) -> {
			if (OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) {
				context.getClaims().claims((claims) -> {
					claims.put("claim-1", "value-1");
					claims.put("claim-2", "value-2");
				});
			}
		};
	}
}

在 JWT 存取權杖中新增授權 (authorities) 作為自訂宣告

為了將資源擁有者的授權 (authorities) 新增到 JWT 存取權杖中,我們可以參考上述的自訂宣告對應方法,並使用 Principal 的授權 (authorities) 填入自訂宣告。

我們定義一個具有一組授權 (authorities) 的範例使用者以進行示範,並在存取權杖中使用這些授權 (authorities) 填入自訂宣告。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext;
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;

@Configuration
public class CustomClaimsWithAuthoritiesConfiguration {
	@Bean
	public UserDetailsService users() {
		UserDetails user = User.withDefaultPasswordEncoder()
				.username("user1") (1)
				.password("password")
				.roles("user", "admin") (2)
				.build();
		return new InMemoryUserDetailsManager(user);
	}

	@Bean
	public OAuth2TokenCustomizer<JwtEncodingContext> jwtTokenCustomizer() { (3)
		return (context) -> {
			if (OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) { (4)
				context.getClaims().claims((claims) -> { (5)
					Set<String> roles = AuthorityUtils.authorityListToSet(context.getPrincipal().getAuthorities())
							.stream()
							.map(c -> c.replaceFirst("^ROLE_", ""))
							.collect(Collectors.collectingAndThen(Collectors.toSet(), Collections::unmodifiableSet)); (6)
					claims.put("roles", roles); (7)
				});
			}
		};
	}
}
1 使用記憶體內 UserDetailsService 定義範例使用者 user1
2 user1 指派角色。
3 定義一個 OAuth2TokenCustomizer<JwtEncodingContext> @Bean,允許自訂 JWT 宣告。
4 檢查 JWT 是否為存取權杖。
5 透過 JwtEncodingContext 存取預設宣告。
6 Principal 物件中提取角色。角色資訊儲存為以 ROLE_ 為字首的字串,因此我們在此處移除字首。
7 將自訂宣告 roles 設定為從上一步收集的角色集合。

作為此自訂的結果,關於使用者的授權 (authorities) 資訊將會作為自訂宣告包含在存取權杖中。