Siirry pääsisältöön

Custom Implementation Example

Avaa ChatGPT:ssä

Tämä opas kuljettaa läpi täydellisen räätälöidyn tietoturvan toteuttamisen käyttäen istuntoon perustuvaa todennusta. Opit, miten neljä keskeistä rajapintaa toimivat yhdessä toteuttamalla ne alusta alkaen.

Useimmissa sovelluksissa tulisi käyttää Spring Securityä

Spring Security integrointi määrittää automaattisesti kaiken, mikä on esitetty tässä. Räätälöidyn tietoturvan rakentaminen on tarpeen vain, jos sinulla on erityisiä vaatimuksia tai et käytä Spring Bootia.

Mitä tulet rakentamaan

Toimiva tietoturvajärjestelmä, jossa on neljä luokkaa:

  • SecurityConfiguration - Määrittelee tietoturvatoiminnat ja uudelleenohjauspaikat
  • SecurityContext - Seuraa, kuka on kirjautunut sisään käyttäen HTTP-istuntoja
  • SecurityManager - Koordinoi tietoturvatarkastuksia ja tarjoaa kirjautumis-/uloskirjautumistoimintoja
  • SecurityRegistrar - Kytkee kaiken yhteen sovelluksen käynnistyessä

Esimerkki käyttää istuntoon perustuvaa tallennusta, mutta voit toteuttaa samat rajapinnat käyttäen tietokantakyselyitä, LDAP:ta tai mitä tahansa muuta todennuspalvelinta.

Kuinka osat toimivat yhdessä

Virta:

  1. SecurityRegistrar toimii käynnistyksessä, luo hallitsijan, rekisteröi arvioijat ja kiinnittää tarkkailijan
  2. SecurityManager koordinoi kaiken - se tarjoaa kontekstin ja määrityksen arvioijille
  3. SecurityContext vastaa kysymykseen "Kuka on kirjautunut sisään?" lukemalla HTTP-istunnoista
  4. SecurityConfiguration vastaa kysymykseen "Mihin uudelleenohjata?" kirjautumis- ja pääsykieltosivuille
  5. Evaluators tekevät pääsypäätöksiä käyttäen kontekstia ja määritystä

Vaihe 1: Määritä tietoturvamääritys

Määritys kertoo tietoturvajärjestelmälle, miten käyttäytyä ja minne ohjata käyttäjiä:

SecurityConfiguration.java
package com.securityplain.security;

import com.webforj.router.history.Location;
import com.webforj.router.security.RouteSecurityConfiguration;
import java.util.Optional;

/**
* Tietoturvamääritys sovellukselle.
*
* <p>
* Määrittelee minne ohjata käyttäjiä, kun todennus on vaadittu tai pääsy on kielletty.
* </p>
*/
public class SecurityConfiguration implements RouteSecurityConfiguration {

@Override
public boolean isEnabled() {
return true;
}

@Override
public boolean isSecureByDefault() {
return false;
}

@Override
public Optional<Location> getAuthenticationLocation() {
return Optional.of(new Location("/login"));
}

@Override
public Optional<Location> getDenyLocation() {
return Optional.of(new Location("/access-denied"));
}
}
  • isEnabled() = true - Tietoturva on aktiivinen
  • isSecureByDefault() = false - Reitit ovat julkisia, ellei niitä ole merkitty (käytä true vaatiaksesi todennusta kaikilta reiteiltä oletuksena)
  • /login - Minne todennusvaatimukset täyttämättömät käyttäjät menevät
  • /access-denied - Minne todennus vaatimukset täyttäneet mutta pääsyoikeudet puuttuvat käyttäjät menevät

Vaihe 2: Toteuta tietoturvakonteksti

Konteksti seuraa, kuka on kirjautunut sisään. Tämä toteutus käyttää HTTP-istuntoja käyttäjätietojen tallentamiseen:

SecurityContext.java
package com.securityplain.security;

import com.webforj.Environment;
import com.webforj.router.security.RouteSecurityContext;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

/**
* Yksinkertainen istuntoon perustuva tietoturvakonteksti.
*
* <p>
* Tallentaa käyttäjäpääsyn ja roolit HTTP-istuntoon. Tämä on minimaalinen toteutus opetus
* tarkoituksiin.
* </p>
*/
public class SecurityContext implements RouteSecurityContext {
private static final String SESSION_USER_KEY = "security.user";
private static final String SESSION_ROLES_KEY = "security.roles";

Kuinka se toimii:

  • isAuthenticated() tarkistaa, onko käyttäjäpääsy olemassa istunnossa
  • getPrincipal() palauttaa käyttäjänimen istunto tallennuksesta
  • hasRole() tarkistaa, sisältääkö käyttäjän roolijoukko määritellyn roolin
  • getAttribute() / setAttribute() hallitsevat mukautettuja tietoturva-attribuutteja
  • Environment.getSessionAccessor() tarjoaa säiekohtaisen pääsyn istuntoon

Vaihe 3: Luo tietoturvahallinta

Hallinta koordinoi tietoturvapäätöksiä. Se laajentaa AbstractRouteSecurityManager -luokkaa, joka käsittelee arvioijaketjuja ja pääsyn kieltoa:

SecurityManager.java
package com.securityplain.security;

import com.webforj.environment.ObjectTable;
import com.webforj.environment.SessionObjectTable;
import com.webforj.router.Router;
import com.webforj.router.security.AbstractRouteSecurityManager;
import com.webforj.router.security.RouteAccessDecision;
import com.webforj.router.security.RouteSecurityConfiguration;
import com.webforj.router.security.RouteSecurityContext;

import java.util.Set;

/**
* Yksinkertainen tietoturvahallintatoteutus.
*
* <p>
* Tarjoaa staattisia menetelmiä kirjautumiseen/uloskirjautumiseen ja hallitsee tietoturvakontekstia.
* </p>
*/
public class SecurityManager extends AbstractRouteSecurityManager {

Kuinka se toimii:

  • Laajentaa AbstractRouteSecurityManager -luokkaa perimään arvioijaketjun logiikka
  • Tarjoaa getConfiguration() ja getSecurityContext() toteutukset
  • Lisää login() autentikoimaan käyttäjiä ja tallentamaan käyttäjätiedot istuntoon
  • Lisää logout() tyhjentämään istunto ja ohjaamaan kirjautumissivulle
  • Käyttää SessionObjectTable yksinkertaiseen istunto tallennukseen
  • Tallentaa itsensä ObjectTable sovelluksen laajuista käyttöä varten

Vaihe 4: Kytke kaikki käynnistyksessä

Rekisteröijä yhdistää kaikki osat kun sovellus käynnistyy:

SecurityRegistrar.java
package com.securityplain.security;

import com.webforj.App;
import com.webforj.AppLifecycleListener;
import com.webforj.annotation.AppListenerPriority;
import com.webforj.router.Router;
import com.webforj.router.security.RouteSecurityObserver;
import com.webforj.router.security.evaluator.AnonymousAccessEvaluator;
import com.webforj.router.security.evaluator.DenyAllEvaluator;
import com.webforj.router.security.evaluator.PermitAllEvaluator;
import com.webforj.router.security.evaluator.RolesAllowedEvaluator;

/**
* Rekisteröi reittien tietoturvakomponentit sovelluksen käynnistyksen aikana.
*
* <p>
* Määrittelee tietoturvahallinnan ja arvioijat reitittimen kanssa.
* </p>
*/
@AppListenerPriority(1)
public class SecurityRegistrar implements AppLifecycleListener {

/**
* {@inheritDoc}
*/
@Override
public void onWillRun(App app) {
// Luo tietoturvahallinta
SecurityManager securityManager = new SecurityManager();
securityManager.saveCurrent(securityManager);

// Rekisteröi sisäänrakennetut arvioijat prioriteettijärjestyksessä
securityManager.registerEvaluator(new DenyAllEvaluator(), 0);
securityManager.registerEvaluator(new AnonymousAccessEvaluator(), 1);
securityManager.registerEvaluator(new PermitAllEvaluator(), 2);
securityManager.registerEvaluator(new RolesAllowedEvaluator(), 3);

// Luo tietoturvatarkkailija ja kiinnitä reitittimeen
RouteSecurityObserver securityObserver = new RouteSecurityObserver(securityManager);
Router router = Router.getCurrent();
if (router != null) {
router.getRenderer().addObserver(securityObserver);
}
}
}

Rekisteröi kuuntelija:

Luo src/main/resources/META-INF/services/com.webforj.AppLifecycleListener seuraavalla sisällöllä:

com.securityplain.security.SecurityRegistrar

Tämä rekisteröi AppLifecycleListener niin, että se suoritetaan sovelluksen käynnistyessä.

Kuinka se toimii:

  • Suoritetaan aikaisessa vaiheessa (@AppListenerPriority(1)) asettaakseen tietoturva ennen reittien lataamista
  • Luo tietoturvahallinnan ja tallentaa sen globaalisti
  • Rekisteröi sisäänrakennetut arvioijat prioriteetti järjestyksessä (pienemmät numerot suoritetaan ensin)
  • Luo tarkkailijan, joka keskeyttää navigoinnin
  • Kiinnittää tarkkailijan reitittimeen, jotta tietotarkastukset tapahtuvat automaattisesti

Kun tämä on suoritettu, tietoturva on aktiivinen kaikelle navigoinnille.

Käyttäminen toteutustasi

Luo kirjautumisnäkymä

Seuraava näkymä käyttää Login komponenttia.

LoginView.java
package com.securityplain.views;

import com.securityplain.security.SecurityManager;
import com.webforj.component.Composite;
import com.webforj.component.login.Login;
import com.webforj.router.Router;
import com.webforj.router.annotation.FrameTitle;
import com.webforj.router.annotation.Route;
import com.webforj.router.history.Location;
import com.webforj.router.security.annotation.AnonymousAccess;

@Route("/login")
@FrameTitle("Kirjautuminen")
@AnonymousAccess
public class LoginView extends Composite<Login> {
private final Login self = getBoundComponent();

public LoginView() {
self.onSubmit(e -> {
var result = SecurityManager.getCurrent().login(
e.getUsername(), e.getPassword()
);

if (result.isGranted()) {
Router.getCurrent().navigate(new Location("/"));
} else {
self.setError(true);
self.setEnabled(true);
}
});

self.whenAttached().thenAccept(c -> self.open());
}
}