Panduan Lengkap Spring Boot 4 · Pelajaran

Pengesahan JWT Pelayan Sumber dan Tuntutan

Sahkan token akses JWT, sahkan penerbit serta khalayak dan ekstrak autoriti daripada tuntutan.

Pelajaran 1 daripada 413 langkah

Pengesahan JWT Pelayan Sumber dan Tuntutan ialah pelajaran Panduan Lengkap Spring Boot 4 percuma di CoddyKit. Ini ialah pelajaran 1 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Panduan Lengkap Spring Boot 4, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Panduan Lengkap Spring Boot 4 merangkumi sejumlah 4 pelajaran.

Peranan Pelayan Sumber

Dalam OAuth2, pelayan sumber ialah API yang menyimpan data yang dilindungi. Pelayan ini tidak melog masuk pengguna atau mengeluarkan token. Tugasnya pada waktu permintaan hanyalah mengesahkan token akses yang telah dikeluarkan oleh pelayan keizinan, kemudian membenarkan panggilan tersebut.

  • Token biasanya ialah JWT (JSON Web Token) yang ditandatangani oleh pelayan keizinan.
  • Pengesahan tidak berkeadaan: pelayan sumber mengesahkan tandatangan dan tuntutan tanpa memanggil pangkalan data.
  • Spring Security menyediakan DSL oauth2ResourceServer khusus untuk tujuan ini.

Dalam pelajaran ini, anda akan mengesahkan JWT, mengesahkan tuntutan iss dan aud, serta menukar tuntutan kepada keizinan Spring.

Anatomi JWT

JWT mempunyai tiga bahagian Base64URL yang dipisahkan oleh titik: header.payload.signature. Muatan membawa tuntutan yang diperiksa oleh pelayan sumber:

  • iss — penerbit, iaitu URL pelayan keizinan.
  • sub — subjek, iaitu id pengguna atau klien.
  • aud — khalayak, iaitu pihak yang dimaksudkan untuk menerima token.
  • exp / nbf / iat — cap masa luput, belum sah sebelum dan dikeluarkan pada.
  • scope atau scp — skop OAuth2 yang diberikan.

Contoh di bawah menunjukkan rupa muatan yang dinyahkod sebagai JSON biasa. Pengesahan bermaksud: tandatangan adalah tulen DAN tuntutan ini boleh diterima.

// 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
}

Konfigurasi Minimum Pelayan Sumber

Dengan spring-boot-starter-oauth2-resource-server pada classpath, anda mengaktifkan pengesahan JWT melalui DSL keselamatan. Pengkonfigurasi jwt() menyambungkan pengesahan tandatangan dan pemeriksaan cap masa standard secara automatik.

Arahkan Spring kepada metadata pelayan keizinan melalui URI penerbit, lalu Spring akan menemukan titik akhir Set JWK (kunci awam) dengan sendiri.

@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();
    }
}

Mengkonfigurasi URI Penerbit

Cara paling kemas untuk menyediakan konfigurasi ialah menggunakan sifat issuer-uri. Semasa permulaan, Spring mengambil {issuer}/.well-known/openid-configuration (atau padanan OAuth2), membaca jwks_uri, lalu membina JwtDecoder yang menyimpan dan memutarkan kunci tandatangan.

Spring juga memasang pengesah penerbit: tuntutan iss bagi setiap token mestilah sama dengan nilai ini, jika tidak token tersebut ditolak.

# application.yml
spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: https://issuer.example.com
          # Optional: pin the audience(s) accepted by this API
          audiences:
            - orders-api

Cara JwtDecoder Mengesahkan

Apabila issuer-uri ditetapkan, Spring membina NimbusJwtDecoder yang disokong oleh Set JWK yang ditemui. Setiap token masuk melalui langkah berikut:

  • Semakan tandatangan — kid token memilih kunci awam daripada Set JWK; tandatangan mestilah sah.
  • Semakan cap masa — exp mestilah pada masa hadapan, manakala nbf mestilah pada masa lalu (dengan sedikit perbezaan jam yang dibenarkan).
  • Semakan penerbit — iss mestilah sepadan dengan penerbit yang dikonfigurasi.

Anda boleh membina penyahkod yang sama secara manual apabila perlu melampirkan pengesah tambahan.

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

Mengesahkan Tuntutan Khalayak

Pengesah lalai menyemak cap masa dan penerbit, tetapi bukan khalayak. Melangkau semakan aud ialah risiko sebenar: token yang dikeluarkan untuk API lain pada penerbit yang sama akan diterima di sini. Inilah serangan kekeliruan token klasik.

Tulis OAuth2TokenValidator<Jwt> tersuai yang memastikan pengecam API anda terdapat dalam senarai aud, kemudian rangkaikannya dengan pengesah lalai.

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);
    }
}

Merangkaikan Pengesah dalam Penyahkod

Gabungkan pengesah khalayak dengan rangkaian lalai bersama penerbit menggunakan DelegatingOAuth2TokenValidator. Susunan tidak penting dari segi ketepatan — semua pengesah mesti lulus — tetapi kekalkan semakan tandatangan dan cap masa (dikendalikan secara dalaman) bersama-sama semakan penerbit dan khalayak.

Bean penyahkod ini mengatasi bean yang dikonfigurasikan secara automatik sambil terus menggunakan semula kunci JWK yang ditemui.

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

Daripada Skop kepada Autoriti

Secara lalai, Spring memetakan tuntutan scope (atau scp) kepada autoriti, dengan menambahkan awalan SCOPE_ pada setiap satunya. Jadi scope: "orders.read" menjadi autoriti SCOPE_orders.read, yang boleh anda wajibkan dalam DSL atau dengan keselamatan kaedah.

  • hasAuthority("SCOPE_orders.read") dalam authorizeHttpRequests.
  • @PreAuthorize("hasAuthority('SCOPE_orders.write')") pada sesuatu kaedah.

Lalai ini berfungsi terus tanpa memerlukan penukar.

http.authorizeHttpRequests(auth -> auth
    .requestMatchers(HttpMethod.GET, "/orders/**")
        .hasAuthority("SCOPE_orders.read")
    .requestMatchers(HttpMethod.POST, "/orders/**")
        .hasAuthority("SCOPE_orders.write")
    .anyRequest().authenticated());

Mengekstrak Peranan daripada Tuntutan Tersuai

Banyak pembekal identiti (Keycloak, Auth0, Entra ID) meletakkan peranan dalam tuntutan bukan standard seperti roles atau realm_access.roles, bukannya dalam scope. Untuk memetakan tuntutan ini, berikan JwtAuthenticationConverter dengan fungsi seakan-akan JwtGrantedAuthoritiesConverter tersuai.

Di sini, kami membaca tatasusunan roles peringkat atas dan menghasilkan autoriti berawalan ROLE_ supaya hasRole(...) berfungsi.

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

Menyambungkan Penukar dan Membaca Tuntutan

Daftarkan penukar pada DSL pelayan sumber supaya ia digunakan untuk membina Authentication. Setelah disambungkan, pengawal anda boleh menyuntik Jwt yang telah disahkan dan membaca sebarang tuntutan secara terus — tuntutan itu telah disahkan sebelum pengendali dijalankan.

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

Membina Autoriti dalam Java Biasa

Logik pemetaan peranan hanyalah transformasi data — logik yang sama dijalankan oleh penukar, tanpa rangka kerja. Petikan di bawah ialah program kendiri yang menunjukkan cara menukar nilai tuntutan kepada autoriti berawalan ROLE_ dan SCOPE_, sama seperti lalai Spring.

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);
    }
}

Semakan Pantas

Pelayan sumber anda menggunakan issuer-uri, jadi tandatangan, tamat tempoh dan penerbit disahkan secara automatik. Seorang penguji penembusan menghantar token yang sah dan belum tamat tempoh, yang dikeluarkan oleh pelayan kebenaran yang sama tetapi dibuat untuk API yang berbeza. Titik akhir anda menerimanya. Apakah pembetulannya?

Imbas Kembali

Anda telah mengkonfigurasi pelayan sumber Spring Boot 4 untuk mengesahkan token akses JWT dari hujung ke hujung:

  • URI penerbit menemui Set JWK secara automatik dan memasang pengesahan tandatangan, cap masa serta penerbit.
  • Khalayak mesti disemak secara jelas dengan OAuth2TokenValidator<Jwt> tersuai untuk menyekat kekeliruan token — lalai tidak melakukannya.
  • Rangkaian pengesah melalui DelegatingOAuth2TokenValidator supaya penerbit + khalayak + lalai semuanya digunakan.
  • Autoriti datang daripada tuntutan scope sebagai SCOPE_* secara lalai; JwtAuthenticationConverter memetakan tuntutan tersuai seperti roles kepada ROLE_*.
  • Pengawal membaca tuntutan yang telah disahkan melalui @AuthenticationPrincipal Jwt.

Sahkan tandatangan, kemudian jangan percayai tuntutan yang belum anda sahkan secara jelas.

Percuma untuk bermula

Pelajari Java dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
21
Pelajaran
84

Soalan Lazim

Adakah pelajaran “Pengesahan JWT Pelayan Sumber dan Tuntutan” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Panduan Lengkap Spring Boot 4, termasuk “Pengesahan JWT Pelayan Sumber dan Tuntutan”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Panduan Lengkap Spring Boot 4 merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Pengesahan JWT Pelayan Sumber dan Tuntutan”?

Sahkan token akses JWT, sahkan penerbit serta khalayak dan ekstrak autoriti daripada tuntutan. Anda berlatih Panduan Lengkap Spring Boot 4 menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Panduan Lengkap Spring Boot 4?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Panduan Lengkap Spring Boot 4 di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 1 daripada 4.

Berapa lamakah pelajaran “Pengesahan JWT Pelayan Sumber dan Tuntutan” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Panduan Lengkap Spring Boot 4 ini?

Ya. Setiap pelajaran Panduan Lengkap Spring Boot 4 menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Pengesahan JWT Pelayan Sumber dan Tuntutan
  2. Klien OAuth2 dan Aliran Kod Keizinan
  3. Keselamatan Kaedah dengan SpEL dan Pengundi Tersuai
  4. Pemeriksaan Token Legap dan Pertukaran Token
← Kembali ke Panduan Lengkap Spring Boot 4