Osa 5

Näkymä- ja metoditason autorisointi

Tutustuimme juuri käyttäjän tunnistamiseen eli autentikointiin. Autentikoinnin lisäksi sovelluksissa on tärkeää varmistaa, että käyttäjä saa tehdä asioita, joita hän yrittää tehdä: autorisointi. Jos käyttäjän tunnistaminen toimii mutta sovellus ei tarkista oikeuksia tarkemmin, on mahdollista päätyä esimerkiksi tilanteeseen, missä käyttäjä pääsee tekemään epätoivottuja asioita.

Näkymätason autorisointi

Määrittelimme aiemmin oikeuksia sovelluksen polkuihin liittyen. Tämä ei kuitenkaan aina riitä, vaan käyttöliitymissä halutaan usein rajoittaa toiminta esimerkiksi käyttäjäroolien perusteella. Thymeleaf-projektiin löytyy liitännäinen, jonka avulla voimme lisätä tarkistuksia HTML-sivuille. Liitännäisen saa käyttöön lisäämällä seuraavan riippuvuuden pom.xml-tiedostoon.

<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>

Kun näkymiien html-elementtiin lisätään sec:-nimiavaruuden määrittely, voidaan sivulle määritellä elementtejä, joiden sisältö näytetään vain esimerkiksi tietyllä roolilla kirjautuneelle käyttäjälle. Seuraavassa esimerkissä teksti "salaisuus" näkyy vain käyttäjälle, jolla on rooli "ADMIN".

<html xmlns="http://www.w3.org/1999/xhtml"
        xmlns:th="http://www.thymeleaf.org"
        xmlns:sec="http://www.springframework.org/security/tags">

    ...
    <div sec:authorize="hasAuthority('ADMIN')">
        <p>salaisuus</p>
    </div>
    ...

Attribuutilla sec:authorize määritellään säännöt, joita tarkistuksessa käytetään. Attribuutille käy mm. arvot isAuthenticated(), hasAuthority('...') ja hasAnyAuthority('...'). Lisää sääntöjä löytyy Spring Securityn dokumentaation kohdasta Expression-Based Access Control.

Metoditason autorisointi

Pelkän näkymätason autorisoinnin ongelmana on se, että usein toimintaa halutaan rajoittaa tarkemmin — esimerkiksi siten, että tietyt operaatiot (esim. poisto tai lisäys) mahdollistetaan vain tietyille käyttäjille tai käyttäjien oikeuksille. Käyttöliittymän näkymää rajoittamalla ei voida rajoittaa käyttäjän tekemiä pyyntöjä, sillä pyynnöt voidaan tehdä myös "käyttöliittymän ohi" — kukaan ei estä käyttäjää lähettämästä tietoa palvelimelle vaikkapa omaa ohjelmaa tai Postmania käyttäen.

Saamme sovellukseemme käyttöön myös metoditason autorisoinnin. Lisäämällä tietoturvakonfiguraatiotiedostoon annotaation @EnableGlobalMethodSecurity(securedEnabled = true, proxyTargetClass = true), Spring Security etsii metodeja, joissa käytetään sopivia annotaatioita ja suojaa ne. Suojaus tapahtuu käytännössä siten, että metodeihin luodaan proxy-metodit; aina kun metodia kutsutaan, kutsutaan ensin tietoturvakomponenttia, joka tarkistaa onko käyttäjä kirjautunut.

Kun konfiguraatiotiedostoon on lisätty annotaatio, on käytössämme muunmuassa annotaatio @Secured. Annotaation avulla voidaan määritellä roolit (tai oikeudet), joiden kohdalla annotoidun metodin kutsuminen on sallittua. Alla olevassa esimerkissä post-metodin käyttöön vaaditaan "ADMIN"-oikeudet.

@Secured("ADMIN")
@PostMapping("/posts")
public String post() {
    // ..
    return "redirect:/posts";
}

Esimerkiksi jos käyttäjien tunnistaminen tapahtuu alla olevalla UserDetailsService-rajapinnan olettamalla metodilla, kukaan ei pääse tekemään POST-pyyntöä polkuun /posts.

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    Account account = accountRepository.findByUsername(username);
    if (account == null) {
        throw new UsernameNotFoundException("No such user: " + username);
    }

    return new org.springframework.security.core.userdetails.User(
            account.getUsername(),
            account.getPassword(),
            true,
            true,
            true,
            true,
            Arrays.asList(new SimpleGrantedAuthority("USER")));
}

Jos taas roolin tai oikeuden "USER" vaihtaa muotoon "ADMIN", pääsevät kaikki tekemään pyynnön kyseiseen metodiin.

Loading

Annotaatio @Secured määrittelee roolit, joilla metodia voi käyttää. Mikäli sovelluksessa haluaa tehdä tarkempaa tarkastelua, käytetään edellisen sijaan annotaatioita @PreAuthorize ja @PostAuthorize-annotaatioita. Lisää aiheesta mm. Baeldungin oppaassa.

Pääsit aliluvun loppuun! Jatka tästä seuraavaan osaan: