JWT-validering og claims på Resource Server
Validér JWT-access tokens, verificér issuers og audiences, og udtræk authorities fra claims.
JWT-validering og claims på Resource Server er en gratis Komplet guide til Spring Boot 4-lektion på CoddyKit. Dette er lektion 1 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Komplet guide til Spring Boot 4, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Komplet guide til Spring Boot 4-kurset indeholder 4 lektioner i alt.
Ressourceserverens rolle
I OAuth2 er en ressourceserver den API, der indeholder beskyttede data. Den logger ikke brugere ind og udsteder ikke tokens. Dens eneste opgave ved en forespørgsel er at validere adgangstokenet, som en autorisationsserver allerede har udstedt, og derefter godkende kaldet.
- Tokens er normalt JWT'er (JSON Web Tokens), som er signeret af autorisationsserveren.
- Valideringen er tilstandsløs: ressourceserveren kontrollerer signaturen og claims uden at kalde en database.
- Spring Security leverer en dedikeret
oauth2ResourceServer-DSL til netop dette.
I denne lektion validerer du JWT'er, kontrollerer claims for iss og aud og omdanner claims til Spring-autorisationer.
Et JWT's opbygning
Et JWT har tre Base64URL-dele adskilt af punktummer: header.payload.signature. Payloaden indeholder claims, som ressourceserveren undersøger:
iss— udstederen, URL'en til autorisationsserveren.sub— emnet, brugerens eller klientens id.aud— målgruppen, det tokenet er beregnet til.exp/nbf/iat— tidsstempler for udløb, tidligste gyldighed og udstedelse.scopeellerscp— tildelte OAuth2-områder.
Eksemplet nedenfor viser, hvordan en afkodet payload ser ud som almindelig JSON. Validering betyder, at signaturen er ægte, OG at disse claims er acceptable.
// A decoded JWT payload (claims) as JSON
{
"iss": "https://issuer.example.com",
"sub": "user-1234",
"aud": ["orders-api"],
"scope": "orders.read orders.write",
"roles": ["ADMIN", "USER"],
"iat": 1735689600,
"nbf": 1735689600,
"exp": 1735693200
}Minimal konfiguration af ressourceserveren
Med spring-boot-starter-oauth2-resource-server på classpathen aktiverer du JWT-validering via sikkerheds-DSL'en. Konfigurationsobjektet jwt() opretter automatisk kontrol af signaturen og standardkontroller af tidsstempler.
Angiv autorisationsserverens metadata via udstederens URI, så finder Spring selv JWK Set-endpointet (de offentlige nøgler).
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/actuator/health").permitAll()
.anyRequest().authenticated())
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(Customizer.withDefaults()));
return http.build();
}
}Konfiguration af udstederens URI
Den reneste måde at sætte det op på er egenskaben issuer-uri. Ved opstart henter Spring {issuer}/.well-known/openid-configuration (eller OAuth2-ækvivalenten), læser jwks_uri og opbygger en JwtDecoder, der cacher og roterer signeringsnøgler.
Den installerer også en udstederalidator: claimet iss i hvert token skal være lig med denne værdi, ellers afvises tokenet.
# application.yml
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://issuer.example.com
# Optional: pin the audience(s) accepted by this API
audiences:
- orders-apiSådan validerer JwtDecoder
Når issuer-uri er angivet, opbygger Spring en NimbusJwtDecoder, der bruger det fundne JWK Set. Hvert indgående token gennemgår følgende:
- Signaturkontrol — tokenets
kidvælger en offentlig nøgle fra JWK Set; signaturen skal kunne verificeres. - Kontrol af tidsstempler —
expskal ligge i fremtiden, ognbfi fortiden (med en lille forskel i urene). - Udstederkontrol —
issskal svare til den konfigurerede udsteder.
Du kan opbygge den samme decoder manuelt, når du har brug for at tilføje ekstra validatorer.
@Bean
JwtDecoder jwtDecoder() {
String issuer = "https://issuer.example.com";
NimbusJwtDecoder decoder =
JwtDecoders.fromIssuerLocation(issuer);
OAuth2TokenValidator<Jwt> withIssuer =
JwtValidators.createDefaultWithIssuer(issuer);
decoder.setJwtValidator(withIssuer);
return decoder;
}Kontrol af audience-claimet
Standardvalidatorerne kontrollerer tidsstempler og udsteder, men ikke målgruppen. Hvis kontrollen af aud springes over, er det en reel risiko: Et token, der er udstedt til et andet API hos den samme udsteder, ville ellers blive accepteret her. Dette er det klassiske angreb med tokenforveksling.
Skriv en tilpasset OAuth2TokenValidator<Jwt>, der sikrer, at dit API's identifikator findes på listen i aud, og kæd den sammen med standardvalidatorerne.
public class AudienceValidator
implements OAuth2TokenValidator<Jwt> {
private final String audience;
public AudienceValidator(String audience) {
this.audience = audience;
}
@Override
public OAuth2TokenValidatorResult validate(Jwt jwt) {
if (jwt.getAudience().contains(audience)) {
return OAuth2TokenValidatorResult.success();
}
OAuth2Error error = new OAuth2Error(
OAuth2ErrorCodes.INVALID_TOKEN,
"Required audience is missing", null);
return OAuth2TokenValidatorResult.failure(error);
}
}Sammenkædning af validatorer i dekoderen
Kombinér målgruppevalidatoren med standardkæden med udsteder ved hjælp af DelegatingOAuth2TokenValidator. Rækkefølgen har ingen betydning for korrektheden — alle validatorer skal godkendes — men behold kontrol af signatur og tidsstempel (som håndteres internt) sammen med kontrol af udsteder og målgruppe.
Denne dekoderbean overskriver den automatisk konfigurerede dekoder, men genbruger stadig de fundne JWK-nøgler.
@Bean
JwtDecoder jwtDecoder(
@Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}") String issuer,
@Value("${api.audience}") String audience) {
NimbusJwtDecoder decoder =
JwtDecoders.fromIssuerLocation(issuer);
OAuth2TokenValidator<Jwt> validator =
new DelegatingOAuth2TokenValidator<>(
JwtValidators.createDefaultWithIssuer(issuer),
new AudienceValidator(audience));
decoder.setJwtValidator(validator);
return decoder;
}Fra omfang til tilladelser
Som standard mapper Spring scope- (eller scp-)attributten til tilladelser og sætter præfikset SCOPE_ foran hver af dem. Så scope: "orders.read" bliver til tilladelsen SCOPE_orders.read, som du kan kræve i DSL'en eller med metodesikkerhed.
hasAuthority("SCOPE_orders.read")iauthorizeHttpRequests.@PreAuthorize("hasAuthority('SCOPE_orders.write')")på en metode.
Denne standardfunktion virker med det samme, uden at du behøver en konverter.
http.authorizeHttpRequests(auth -> auth
.requestMatchers(HttpMethod.GET, "/orders/**")
.hasAuthority("SCOPE_orders.read")
.requestMatchers(HttpMethod.POST, "/orders/**")
.hasAuthority("SCOPE_orders.write")
.anyRequest().authenticated());Hentning af roller fra en tilpasset attribut
Mange identitetsudbydere (Keycloak, Auth0, Entra ID) placerer roller i en ikke-standardiseret attribut som roles eller realm_access.roles i stedet for i scope. Hvis du vil mappe disse, skal du angive en JwtAuthenticationConverter med en tilpasset funktion, der minder om JwtGrantedAuthoritiesConverter.
Her læser vi et array på øverste niveau med navnet roles og udsender tilladelser med præfikset ROLE_, så hasRole(...) virker.
@Bean
JwtAuthenticationConverter jwtAuthConverter() {
JwtAuthenticationConverter converter =
new JwtAuthenticationConverter();
converter.setJwtGrantedAuthoritiesConverter(jwt -> {
List<String> roles =
jwt.getClaimAsStringList("roles");
if (roles == null) return List.of();
return roles.stream()
.map(r -> new SimpleGrantedAuthority("ROLE_" + r))
.collect(Collectors.toList());
});
return converter;
}Tilslutning af konverteren og læsning af attributter
Registrér konverteren i DSL'en for ressource-serveren, så den bruges til at opbygge Authentication. Når den er tilsluttet, kan dine controllere injicere den validerede Jwt og læse enhver attribut direkte — den er allerede verificeret, når håndteringsmetoden kører.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain chain(HttpSecurity http,
JwtAuthenticationConverter converter) throws Exception {
http.oauth2ResourceServer(oauth2 -> oauth2
.jwt(jwt -> jwt.jwtAuthenticationConverter(converter)));
return http.build();
}
}
@RestController
class MeController {
@GetMapping("/me")
Map<String, Object> me(@AuthenticationPrincipal Jwt jwt) {
return Map.of(
"sub", jwt.getSubject(),
"issuer", jwt.getIssuer().toString(),
"roles", jwt.getClaimAsStringList("roles"));
}
}Opbygning af tilladelser i almindelig Java
Logikken til rolletilknytning er blot en datatransformation — den samme logik, som konverteren kører, men uden frameworket. Kodestykket nedenfor er et selvstændigt program, der viser, hvordan en attributværdi omdannes til tilladelser med præfikserne ROLE_ og SCOPE_, præcis som i Springs standardfunktion.
import java.util.*;
import java.util.stream.*;
public class AuthorityMapping {
static List<String> fromRoles(List<String> roles) {
return roles.stream()
.map(r -> "ROLE_" + r)
.collect(Collectors.toList());
}
static List<String> fromScope(String scope) {
return Arrays.stream(scope.split(" "))
.filter(s -> !s.isBlank())
.map(s -> "SCOPE_" + s)
.collect(Collectors.toList());
}
public static void main(String[] args) {
List<String> authorities = new ArrayList<>();
authorities.addAll(fromRoles(List.of("ADMIN", "USER")));
authorities.addAll(fromScope("orders.read orders.write"));
System.out.println(authorities);
}
}Hurtig kontrol
Din ressource-server bruger issuer-uri, så signatur, udløbstidspunkt og udsteder valideres automatisk. En sikkerhedstester sender et gyldigt token, der ikke er udløbet, og som er udstedt af den samme autorisationsserver, men til et andet API. Dit slutpunkt accepterer det. Hvad er løsningen?
Opsummering
Du har konfigureret en Spring Boot 4-ressource-server til at validere JWT-adgangstokens fra ende til anden:
- Udstederens URI finder automatisk JWK-sættet og aktiverer validering af signatur, tidsstempel og udsteder.
- Målgruppe skal kontrolleres eksplicit med en tilpasset
OAuth2TokenValidator<Jwt>for at blokere tokenforveksling — standardvalidatorerne gør ikke dette. - Validatorer kædes sammen via
DelegatingOAuth2TokenValidator, så udsteder, målgruppe og standardvalidatorer alle anvendes. - Tilladelser kommer som standard fra
scope-attributten somSCOPE_*; enJwtAuthenticationConvertermapper tilpassede attributter somrolestilROLE_*. - Controllere læser verificerede attributter via
@AuthenticationPrincipal Jwt.
Validér signaturen, og stol derefter aldrig på en attribut, som du ikke udtrykkeligt har verificeret.
Lær Java med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 21
- Lektioner
- 84
Ofte stillede spørgsmål
Er lektionen “JWT-validering og claims på Resource Server” gratis?
Ja — alle 3 lektioner i læringssporet Komplet guide til Spring Boot 4, inklusive “JWT-validering og claims på Resource Server”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Komplet guide til Spring Boot 4-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “JWT-validering og claims på Resource Server”?
Validér JWT-access tokens, verificér issuers og audiences, og udtræk authorities fra claims. Du øver dig i Komplet guide til Spring Boot 4 med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Komplet guide til Spring Boot 4?
Der kræves ingen tidligere erfaring. Komplet guide til Spring Boot 4 på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 1 af 4.
Hvor lang tid tager lektionen “JWT-validering og claims på Resource Server”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Komplet guide til Spring Boot 4-lektion?
Ja. Alle Komplet guide til Spring Boot 4-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- JWT-validering og claims på Resource Server
- OAuth2-klient og Authorization Code Flow
- Metodesikkerhed med SpEL og brugerdefinerede voters
- Introspektion og tokenudveksling for opaque tokens