Custom Implementation Example
Tämä opas käy läpi täydellisen mukautetun turvallisuusratkaisun rakentamisen istuntopohjaista todennusta käyttäen. Opit, kuinka neljä keskeistä rajapintaa toimii yhdessä toteuttamalla ne alusta alkaen.
Spring Security -integraatio konfiguroi automaattisesti kaiken tämän. Rakenna mukautettu turvallisuus vain, jos sinulla on erityisiä vaatimuksia tai et käytä Spring Bootia.
Mitä rakennat
Toimiva turvallisuusjärjestelmä neljällä luokalla:
- SecurityConfiguration - Määrittelee turvallisuuskäyttäytymisen ja uudelleenohjauspaikat
- SecurityContext - Seuraa, kuka on kirjautuneena HTTP-istuntojen avulla
- SecurityManager - Koordinoi turvallisuustarkastuksia ja tarjoaa kirjautumis-/uloskirjautumisratkaisuja
- SecurityRegistrar - Yhdistää kaiken sovelluksen käynnistyksen yhteydessä
Tässä esimerkissä käytetään istuntopohjaista tallennusta, mutta voit toteuttaa samat rajapinnat käyttämällä tietokantakyselyitä, LDAP:ia tai mitä tahansa muuta todennusjärjestelmää.
Miten osat toimivat yhdessä
Virta:
SecurityRegistrartoimii käynnistyksessä, luo hallitsijan, rekisteröi arvioijat ja liittää tarkkailijanSecurityManagerkoordinoi kaiken - se tarjoaa kontekstin ja konfiguraation arvioijilleSecurityContextvastaa kysymykseen "Kuka on kirjautuneena?" lukemalla HTTP-istunnoistaSecurityConfigurationvastaa kysymykseen "Minne ohjata?" kirjautumis- ja käyttöoikeuden hylkäämisen sivuilleEvaluatorstekevät käyttöoikeuspäätöksiä käyttäen kontekstia ja konfiguraatiota
Vaihe 1: Määrittele turvallisuuskonfiguraatio
Konfiguraatio kertoo turvallisuusjärjestelmälle, miten toimia ja minne ohjata käyttäjiä:
package com.securityplain.security;
import com.webforj.router.history.Location;
import com.webforj.router.security.RouteSecurityConfiguration;
import java.util.Optional;
/**
* Sovelluksen turvallisuuskonfiguraatio.
*
* <p>
* Määrittelee, minne ohjata käyttäjiä, kun todennusta vaaditaan tai pääsy hylätään.
* </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- Turvallisuus on aktiivinenisSecureByDefault() = false- Reitit ovat julkisia, ellei niitä ole merkitty (käytätruevaatiaksesi todennusta kaikilta reiteiltä oletuksena)/login- Minne tunnistautumattomat käyttäjät menevät/access-denied- Minne todennettujen käyttäjien, joilla ei ole lupia, tulee mennä
Vaihe 2: Toteuta turvallisuuskonteksti
Konteksti seuraa, kuka on kirjautuneena. Tämä toteutus käyttää HTTP-istuntoja käyttäjätietojen tallentamiseen:
Miten se toimii:
isAuthenticated()tarkistaa, onko käyttäjäprincipaali olemassa istunnossagetPrincipal()hakee käyttäjätunnuksen istuntovarastostahasRole()tarkistaa, sisältääkö käyttäjän roolijoukko määritellyn roolingetAttribute()/setAttribute()hallinnoi mukautettuja turvallisuusattribuuttejaEnvironment.getSessionAccessor()tarjoaa säikeiden turvallisen pääsyn istuntoon
Vaihe 3: Luo turvallisuuden hallitsija
Hallitsija koordinoi turvallisuuspäätöksiä. Se laajentaa AbstractRouteSecurityManager-luokkaa, joka käsittelee arviointiketjuja ja käyttöoikeuden hylkäystä:
Miten se toimii:
- Laajentaa
AbstractRouteSecurityManager-luokkaa perimään arviointiketjun logiikka - Tarjoaa
getConfiguration()- jagetSecurityContext()-toteutukset - Lisää
login()-metodin käyttäjien todennusta varten ja tallentaa käyttöoikeudet istuntoon - Lisää
logout()-metodin tyhjentämään istunnon ja ohjaamaan kirjautumissivulle - Käyttää
SessionObjectTableyksinkertaista istuntovarastointia varten - Tallentaa itsensä
ObjectTablesovelluksen laajuista pääsyä varten
Vaihe 4: Liitä kaikki käynnistyksessä
Rekisteröijä yhdistää kaikki osat, kun sovellus käynnistyy:
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 reitin turvallisuuskomponentit sovelluksen käynnistyksen aikana.
*
* <p>
* Asettuu turvallisuusmanageri ja arvioijat reitittimen kanssa.
* </p>
*/
@AppListenerPriority(1)
public class SecurityRegistrar implements AppLifecycleListener {
/**
* {@inheritDoc}
*/
@Override
public void onWillRun(App app) {
// Luo turvallisuusmanageri
SecurityManager securityManager = new SecurityManager();
securityManager.saveCurrent(securityManager);
// Rekisteröi sisäänrakennetut arvioijat prioriteetti järjestyksessä
securityManager.registerEvaluator(new DenyAllEvaluator(), 0);
securityManager.registerEvaluator(new AnonymousAccessEvaluator(), 1);
securityManager.registerEvaluator(new PermitAllEvaluator(), 2);
securityManager.registerEvaluator(new RolesAllowedEvaluator(), 3);
// Luo turvallisuustarkkailija ja liitä se 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 sisältäen:
com.securityplain.security.SecurityRegistrar
Tämä rekisteröi AppLifecycleListener, jotta se suoritetaan sovelluksen käynnistyessä.
Miten se toimii:
- Suorittaa aikaisin (
@AppListenerPriority(1)) asettaakseen turvallisuuden ennen reittien lataamista - Luo turvallisuusmanagerin ja tallentaa sen globaalisti
- Rekisteröi sisäänrakennetut arvioijat prioriteetti järjestyksessä (alac numerot suoritetaan ensin)
- Luo tarkkailijan, joka puuttuu navigointiin
- Liittää tarkkailijan reitittimeen, jotta turvallisuustarkastukset tapahtuvat automaattisesti
Kun tämä on suoritettu, turvallisuus on aktiivinen kaikissa navigoinneissa.
Käytä toteutustasi
Luo kirjautumisikkuna
Seuraava ikkuna käyttää Login -komponenttia.
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("Kirjaudu sisään")
@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());
}
}