Spring Boot 4:n kattava opas · Oppitunti

Todennus ja valtuutus

Määrittäkää käyttäjien todennus tietokantojen avulla ja määritelkää eri rooleille ja poluille käyttöoikeussäännöt.

Oppitunti 2/412 vaihetta

Todennus ja valtuutus on ilmainen Spring Boot 4:n kattava opas-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Spring Boot 4:n kattava opas-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Spring Boot 4:n kattava opas-kurssilla on yhteensä 4 oppituntia.

Todentaminen ja valtuutus

Tietoturvassa puhutaan usein kahdesta keskeisestä käsitteestä: todentamisesta ja valtuutuksesta.

  • Todentamisessa (AuthN) varmistetaan, kuka olet. Se on kuin näyttäisit henkilöllisyystodistuksesi todistaaksesi henkilöllisyytesi.
  • Valtuutuksessa (AuthZ) määritetään, mitä saat tehdä sen jälkeen, kun henkilöllisyytesi on vahvistettu. Tämä vastaa sitä, että henkilöllisyystodistuksesi antaa sinulle pääsyn tiettyihin alueisiin.

Tietokantatodentamisen kulku

Spring Security voi todentaa käyttäjät tietokantaan tallennettujen käyttäjätietojen avulla. Käyttäjien kovakoodauksen sijaan voimme yhdistää sovelluksen oikeaan tietolähteeseen.

Prosessi sisältää yleensä seuraavat vaiheet:

  • Käyttäjä yrittää kirjautua sisään.
  • Spring Security hakee käyttäjätiedot (käyttäjänimen, salasanan ja roolit) tietokannasta.
  • Se tarkistaa salasanan.
  • Jos tarkistus onnistuu, käyttäjä todennetaan.

Käyttäjätietojen hakeminen

Spring Securityn keskeinen rajapinta käyttäjäkohtaisten tietojen hakemiseen on UserDetailsService. Toteutat tämän rajapinnan, jotta Spring tietää, miten käyttäjät haetaan tietokannastasi.

Rajapinnassa on yksi metodi: loadUserByUsername(String username). Tämä metodi palauttaa UserDetails-olion, joka sisältää käyttäjän käyttäjänimen, salasanan ja oikeudet (roolit).

Mukautettu UserDetailsService

Luodaan yksinkertainen UserDetailsService. Toistaiseksi simuloimme käyttäjien hakemista luettelosta, mutta oikeassa sovelluksessa tiedot haettaisiin tietokannasta.

Huomaa, että palautamme User-olion, joka on yleinen UserDetails-rajapinnan toteutus.

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.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@Service
public class MyUserDetailsService implements UserDetailsService {

    private final Map<String, UserDetails> users = new HashMap<>();

    public MyUserDetailsService(PasswordEncoder passwordEncoder) {
        // Simulate users from a database
        users.put("user", User.builder()
            .username("user")
            .password(passwordEncoder.encode("password"))
            .roles("USER")
            .build());
        users.put("admin", User.builder()
            .username("admin")
            .password(passwordEncoder.encode("adminpass"))
            .roles("ADMIN", "USER")
            .build());
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserDetails user = users.get(username);
        if (user == null) {
            throw new UsernameNotFoundException("User not found: " + username);
        }
        return user;
    }
}

Salasanojen suojaaminen

Salasanojen tallentaminen selväkielisenä on merkittävä tietoturvariski. Spring Security edellyttää, että käytät PasswordEncoder-toteutusta salasanojen turvalliseen tiivistämiseen (koodaamiseen).

Yleisin toteutus on BCryptPasswordEncoder, joka käyttää vahvaa tiivistealgoritmia. Määrität sen Spring-pavuksi.

Todentamisen yhdistäminen

Yhdistetään nyt UserDetailsService ja PasswordEncoder Spring Securityn määrityksiin. Määritämme SecurityFilterChain-pavun.

Tämä suodatinketju kertoo Springille, miten pyynnöt käsitellään, myös todentamisen osalta.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final UserDetailsService userDetailsService;

    public SecurityConfig(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable()) // Disable CSRF for simplicity in this example
            .authorizeHttpRequests(authorize -> authorize
                .anyRequest().authenticated() // All other requests require authentication
            )
            .formLogin(form -> form.permitAll()); // Enable form login for browser access
        return http.build();
    }
}

Täydellinen todentamisesimerkki

Tässä on täydellinen Spring Boot -sovellus, joka havainnollistaa perustason todentamista mukautetun UserDetailsService- ja PasswordEncoder-toteutuksen avulla. Kokeile käyttää osoitetta /hello kirjautumisen jälkeen!

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
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.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@SpringBootApplication
public class AuthApp {
    public static void main(String[] args) {
        SpringApplication.run(AuthApp.class, args);
    }
}

@RestController
class HelloController {
    @GetMapping("/hello")
    public String hello() {
        return "Hello, authenticated user!";
    }
}

@Service
class MyUserDetailsService implements UserDetailsService {
    private final Map<String, UserDetails> users = new HashMap<>();

    public MyUserDetailsService(PasswordEncoder passwordEncoder) {
        users.put("user", User.builder()
            .username("user")
            .password(passwordEncoder.encode("password"))
            .roles("USER")
            .build());
        users.put("admin", User.builder()
            .username("admin")
            .password(passwordEncoder.encode("adminpass"))
            .roles("ADMIN", "USER")
            .build());
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserDetails user = users.get(username);
        if (user == null) {
            throw new UsernameNotFoundException("User not found: " + username);
        }
        return user;
    }
}

@Configuration
@EnableWebSecurity
class SecurityConfig {
    private final UserDetailsService userDetailsService;

    public SecurityConfig(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(authorize -> authorize
                .anyRequest().authenticated()
            )
            .formLogin(form -> form.permitAll());
        return http.build();
    }
}

Mitä käyttäjä saa tehdä

Kun käyttäjä on todennettu, valtuutuksessa määritetään, mitä resursseja tai toimintoja hän saa käyttää. Tämä tarkistetaan käyttäjälle määritettyjen roolien tai oikeuksien perusteella.

Esimerkiksi käyttäjä roolilla "ADMIN" voi käyttää ylläpitosivuja, kun taas käyttäjä roolilla "USER" voi nähdä vain oman profiilinsa.

Polkujen suojaaminen roolin perusteella

Spring Securityn avulla voit määrittää valtuutussäännöt suoraan SecurityFilterChain-pavussa. Voit suojata tiettyjä URL-malleja roolien perusteella.

Keskeiset metodit:

  • .requestMatchers("/admin/**").hasRole("ADMIN"): Vain käyttäjät, joilla on 'ADMIN'-rooli, voivat käyttää osoitteita polun /admin/ alla.
  • .requestMatchers("/user/**").hasAnyRole("USER", "ADMIN"): Käyttäjät, joilla on 'USER'- tai 'ADMIN'-rooli.
  • .anyRequest().authenticated(): Kaikki muut pyynnöt edellyttävät, että käyttäjä on todennettu.

Valtuutus käytännössä

Lisätään valtuutussäännöt edelliseen esimerkkiimme. Kokeile kirjautua käyttäjänä 'user' (salasana: 'password') ja ylläpitäjänä 'admin' (salasana: 'adminpass') ja käyttää eri päätepisteitä.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
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.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@SpringBootApplication
public class AuthZApp {
    public static void main(String[] args) {
        SpringApplication.run(AuthZApp.class, args);
    }
}

@RestController
class SecuredController {
    @GetMapping("/public")
    public String publicPage() {
        return "This is a public page.";
    }

    @GetMapping("/user/profile")
    public String userProfile() {
        return "Welcome, user! This is your profile.";
    }

    @GetMapping("/admin/dashboard")
    public String adminDashboard() {
        return "Welcome, admin! This is the admin dashboard.";
    }
}

@Service
class MyUserDetailsService implements UserDetailsService {
    private final Map<String, UserDetails> users = new HashMap<>();

    public MyUserDetailsService(PasswordEncoder passwordEncoder) {
        users.put("user", User.builder()
            .username("user")
            .password(passwordEncoder.encode("password"))
            .roles("USER")
            .build());
        users.put("admin", User.builder()
            .username("admin")
            .password(passwordEncoder.encode("adminpass"))
            .roles("ADMIN", "USER")
            .build());
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserDetails user = users.get(username);
        if (user == null) {
            throw new UsernameNotFoundException("User not found: " + username);
        }
        return user;
    }
}

@Configuration
@EnableWebSecurity
class SecurityConfig {
    private final UserDetailsService userDetailsService;

    public SecurityConfig(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(authorize -> authorize
                .requestMatchers("/public").permitAll() // Public access
                .requestMatchers("/user/**").hasRole("USER") // Only USER role
                .requestMatchers("/admin/**").hasRole("ADMIN") // Only ADMIN role
                .anyRequest().authenticated() // All others need authentication
            )
            .formLogin(form -> form.permitAll());
        return http.build();
    }
}

Pikatarkistus

Kertaa todentamisen ja valtuutuksen käsitteet sekä niihin liittyvät komponentit.

Kertaus ja seuraavat vaiheet

Hienoa työtä! Tällä oppitunnilla opit:

  • Erottamaan todentamisen ja valtuutuksen toisistaan.
  • Ymmärtämään, miten Spring Security käyttää tietokantoja todentamiseen.
  • Toteuttamaan mukautetun UserDetailsService-komponentin käyttäjätietojen hakemista varten.
  • Käyttämään PasswordEncoder-komponenttia käyttäjien salasanojen suojaamiseen.
  • Määrittämään rooleihin perustuvia URL-valtuutussääntöjä.

Seuraavaksi tutustut edistyneempiin suojausominaisuuksiin, kuten tilattomien rajapintojen JWT-pohjaiseen todentamiseen!

Aloita maksutta

Opi Java tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
21
Oppitunnit
84

Usein kysytyt kysymykset

Onko oppitunti ”Todennus ja valtuutus” ilmainen?

Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Spring Boot 4:n kattava opas-oppimispolun 3 oppituntia, myös oppitunnin “Todennus ja valtuutus”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Spring Boot 4:n kattava opas-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Todennus ja valtuutus”?

Määrittäkää käyttäjien todennus tietokantojen avulla ja määritelkää eri rooleille ja poluille käyttöoikeussäännöt. Harjoittelet Spring Boot 4:n kattava opas-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Spring Boot 4:n kattava opas-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Spring Boot 4:n kattava opas-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.

Kuinka kauan ”Todennus ja valtuutus”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Spring Boot 4:n kattava opas-oppitunnilla?

Kyllä. Jokainen Spring Boot 4:n kattava opas-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Spring Securityn perusteet
  2. Todennus ja valtuutus
  3. JWT-pohjainen tietoturva
  4. OAuth2:n ja sosiaalisen kirjautumisen integrointi
← Takaisin: Spring Boot 4:n kattava opas