
Einführung
Seit der ersten Veröffentlichung ist viel Zeit vergangen ( Link zum vorherigen Artikel ). Was hat sich geändert?
- verbesserte Stabilität des Gesamtsystems;
- Lazy Component Loading implementiert;
- Eingebautes Basis-Listener-System
- eingebaute Unterstützung für aspektorientierte Programmierung (zur Lösung von Problemen mit mittlerem Schwierigkeitsgrad, ansonsten empfehle ich Ihnen, die AspectJ-Bibliothek für den Rest zu verwenden)
- neuer RequestFactory-Bootloader
- integrierte Arbeit mit Cache basierend auf EhCache, Guava
- Die Arbeit mit Streams ist integriert (sowohl die Initialisierung über die Annotation @SimpleTask als auch die direkte Arbeit mit dem Pool).
** Module
- Modul für die Arbeit mit der Datenbank (leichtes ORM mit Unterstützung für JPA, Transaktionen, NO-SQL-Treiber - Orient, Crud-Methoden, Repository-System und automatisch generierte Abfragen aus der Funktion der Repository-Klasse)
- Web-Muzzle-Modul (Link-Mapping über Anmerkungen, Unterstützung für benutzerdefinierte Produzenten / Konsumenten, Rendering-Seite für Geschwindigkeitsvorlagen, grundlegende Sicherheitsanforderungen, Sitzungen, Cookies, SSL) basierend auf Netty 4.1.30.Final
Rahmenstruktur

"Das ist natürlich alles gut", sagen Sie, "aber funktioniert tatsächlich alles?"
"Ja, es funktioniert. Ich bitte um einen Schnitt."
Beispiel für einen Implementierungsprozess
Um das Beispiel zu implementieren, werde ich Maven 3 und Intelijj Idea 2018.2 verwenden.
1) Verbinden Sie die Abhängigkeiten:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>example-webapp</artifactId> <groupId>org.ioc</groupId> <packaging>jar</packaging> <version>0.0.1</version> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <.source>1.8</source> <target>1.8</target> </configuration> <executions> <execution> <id>default-testCompile</id> <phase>test-compile</phase> <goals> <goal>testCompile</goal> </goals> </execution> </executions> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.ioc</groupId> <artifactId>context-factory</artifactId> <version>2.2.4.STABLE</version> </dependency> <dependency> <groupId>org.ioc</groupId> <artifactId>orm-factory</artifactId> <version>2.2.4.STABLE</version> </dependency> <dependency> <groupId>org.ioc</groupId> <artifactId>web-factory</artifactId> <version>2.2.4.STABLE</version> </dependency> </dependencies> <repositories> <repository> <id>context</id> <url>https://raw.github.com/GenCloud/ioc_container/context</url> </repository> <repository> <id>cache</id> <url>https://raw.github.com/GenCloud/ioc_container/cache</url> </repository> <repository> <id>threading</id> <url>https://raw.github.com/GenCloud/ioc_container/threading</url> </repository> <repository> <id>orm</id> <url>https://raw.github.com/GenCloud/ioc_container/orm</url> </repository> <repository> <id>web</id> <url>https://raw.github.com/GenCloud/ioc_container/web</url> </repository> </repositories> </project>
** Er ist leider noch nicht nach Maven Central gezogen.
Projektstruktur:

Standard-MVC-Muster, nicht wahr?
Erstellen Sie einen Einstiegspunkt für die Anwendung:
package org.examples.webapp; import org.ioc.annotations.context.ScanPackage; import org.ioc.annotations.modules.CacheModule; import org.ioc.annotations.modules.DatabaseModule; import org.ioc.annotations.modules.ThreadingModule; import org.ioc.annotations.modules.WebModule; import org.ioc.context.starter.IoCStarter; @WebModule @CacheModule @ThreadingModule @DatabaseModule @ScanPackage(packages = {"org.examples.webapp"}) public class AppMain { public static void main(String[] args) { IoCStarter.start(AppMain.class); } }
** Erklärungen:
Annotation @ScanPackages - Definiert Kontextpakete zur Identifizierung von Komponenten (in gewöhnlichen Personen - "Bins").
Annotation @WebModule - dient zum Verbinden und Initialisieren einer Webfactory .
Annotation @CacheModule - wird zum Verbinden und Initialisieren der Cache-Factory verwendet. Sie wird für den korrekten Betrieb von ORM verwendet (in zukünftigen Versionen ist keine Annotation erforderlich).
Annotation @ThreadingModule - dient zum Verbinden und Initialisieren einer Thread-Factory. Sie wird verwendet, damit die Web-Factory ordnungsgemäß funktioniert (in zukünftigen Versionen ist keine Annotation erforderlich).
Annotation @DatabaseModule - Dient zum Verbinden und Initialisieren einer ORM-Factory.
Alle Fabriken verfügen über Standardkonfiguratoren, die Sie ändern können, indem Sie die Funktionen der von den Fabriken verwendeten Einstellungen neu definieren (in jeder Modulanmerkung wird der Klassenkonfigurator neu definiert - Klasse <?> AutoConfigurationClass (), Standard-WebAutoConfiguration.class ) oder jede Konfiguration mithilfe der Annotation @Exclude in main deaktivieren Klassenzimmer.
Das Dienstprogramm IoCStarter ist die Hauptklasse für die Kontextinitialisierung.
Nun, alles scheint fertig zu sein, der Kontext wird initialisiert, das Web funktioniert auf dem Standardport 8081, aber es gibt keinen Link, und wenn wir zur Site gehen, gibt es uns nicht wirklich etwas. Nun, mach weiter.
Lassen Sie uns eine Konfigurationsdatei für unsere Module erstellen. Standardmäßig werden alle Konfigurationen aus {working_dir} /configs/default_settings.properties geladen - wir erstellen sie auf dem entsprechenden Pfad.
# Threading ioc.threads.poolName=shared ioc.threads.availableProcessors=4 ioc.threads.threadTimeout=0 ioc.threads.threadAllowCoreTimeOut=true ioc.threads.threadPoolPriority=NORMAL # Event dispather # - () ( ) ioc.dispatcher.availableDescriptors=4 # Cache # (EhFactory|GuavaFactory) cache.factory=org.ioc.cache.impl.EhFactory # Datasource # (-, - ) #LOCAL, LOCAL_SERVER, REMOTE datasource.orient.database-type=LOCAL # datasource.orient.url=./database # ( ) datasource.orient.database=orient # datasource.orient.username=admin # datasource.orient.password=admin # (create, dropCreate, refresh, none) datasource.orient.ddl-auto=dropCreate # , datasource.orient.showSql=true # Web server # web.server.port=8081 # SSL web.server.ssl-enabled=false # in seconds # ( 7200 . = 2 ) web.server.security.session.timeout=300 # - web.server.velocity.input.encoding=UTF-8 web.server.velocity.output.encoding=UTF-8 # - web.server.velocity.resource.loader=file # web.server.velocity.resource.loader.class=org.apache.velocity.runtime.resource.loader.FileResourceLoader # - web.server.velocity.resource.loading.path=./public
Als nächstes benötigen wir eine Benutzerentität und ihr verwaltendes Repository:
Implementierung der TblAccount-Entität:
package org.examples.webapp.domain.entity; import org.ioc.web.security.user.UserDetails; import javax.persistence.*; import java.util.Collections; import java.util.List; @Entity public class TblAccount implements UserDetails { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private long id; @Column(name = "username") private String username; @Column(name = "password") private String password; @Transient private String repeatedPassword; public String getRepeatedPassword() { return repeatedPassword; } public void setRepeatedPassword(String repeatedPassword) { this.repeatedPassword = repeatedPassword; } @Override public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Override public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public List<String> getRoles() { return Collections.singletonList("ROLE_USER"); } }
** Erklärungen:
Alles ist Standard wie bei allen JPA-unterstützenden Frameworks. Ordnen Sie die Entität mit @ .Entity zu , erstellen Sie den Primärschlüssel mit der Annotation @ .Id und ordnen Sie die Spalten mit der Annotation @Column zu. und von UserDetails erben, um die Entität im Sicherheitsmodul zu identifizieren.
Implementierung des TblAccountRepository Entity Repository:
package org.examples.webapp.domain.repository; import org.examples.webapp.domain.entity.TblAccount; import org.ioc.annotations.context.IoCRepository; import org.ioc.orm.repositories.CrudRepository; import javax.transaction.Transactional; @IoCRepository public interface TblAccountRepository extends CrudRepository<TblAccount, Long> { @Transactional TblAccount findByUsernameEq(String username); }
** Erklärungen:
Annotation @IoCRepository - dient dazu, anhand des Kontexts zu bestimmen, dass die Klasse ein Repository ist und „anders“ verarbeitet werden muss .
Unterstützt Standard- CRUD- Funktionen:
- Entitätsabruf (ID-ID) - Ruft eine Entität vom Typ Entität aus der Datenbank oder aus dem Cache per Primärschlüssel ab.
- List fetchAll () - ruft alle Entitäten des Entitätstyps ab und lädt sie vorab in den Cache.
- void save (Entity Entity) - Erstellt / aktualisiert eine Entität vom Typ Entity sowohl in der Datenbank als auch im Cache.
- void delete (Entity-Entität) - Löscht eine Entität vom Typ Entity sowohl aus der Datenbank als auch aus dem Cache.
- Boolescher Wert vorhanden (ID-ID) - Überprüft mithilfe des Primärschlüssels, ob eine Entität in der Datenbank vorhanden ist.
Alle CRUD-Anforderungen treten in einer Transaktion auf.
Es unterstützt die automatische Generierung von Abfragen durch Neudefinition von Funktionen mit Schlüsselwörtern, wie in der obigen Implementierung ( TblAccount findByUsernameEq (String username) ) und Aufrufen registrierter Abfragen ( NamedQuery ).
Funktion findByUsernameEq (String username) - sucht anhand seines Benutzernamenfelds nach einer Entität. Generierte Anfrage:
select * from tbl_account where username = 'username'
Als nächstes benötigen wir eine Ebene für die Verwaltung der Geschäftslogik.
AccountService-Implementierungen:
package org.examples.webapp.service; import org.examples.webapp.domain.entity.TblAccount; import org.examples.webapp.domain.repository.TblAccountRepository; import org.examples.webapp.responces.IMessage; import org.ioc.annotations.context.IoCComponent; import org.ioc.annotations.context.IoCDependency; import org.ioc.web.model.http.Request; import org.ioc.web.security.configuration.SecurityConfigureAdapter; import org.ioc.web.security.encoder.bcrypt.BCryptEncoder; import org.ioc.web.security.user.UserDetails; import org.ioc.web.security.user.UserDetailsProcessor; import java.util.Objects; import static org.examples.webapp.responces.IMessage.Type.ERROR; import static org.examples.webapp.responces.IMessage.Type.OK; @IoCComponent public class AccountService implements UserDetailsProcessor { @IoCDependency private TblAccountRepository tblAccountRepository; @IoCDependency private BCryptEncoder bCryptEncoder; @IoCDependency private SecurityConfigureAdapter securityConfigureAdapter; @Override public UserDetails loadUserByUsername(String username) { return tblAccountRepository.findByUsernameEq(username); } public void save(TblAccount tblAccount) { tblAccountRepository.save(tblAccount); } public void delete(TblAccount tblAccount) { tblAccountRepository.delete(tblAccount); } public IMessage tryCreateUser(String username, String password, String repeatedPassword) { if (username == null || username.isEmpty() || password == null || password.isEmpty() || repeatedPassword == null || repeatedPassword.isEmpty()) { return new IMessage(ERROR, "Invalid request parameters!"); } if (!Objects.equals(password, repeatedPassword)) { return new IMessage(ERROR, "Repeated password doesn't match!"); } final UserDetails userDetails = loadUserByUsername(username); if (userDetails != null) { return new IMessage(ERROR, "Account already exists!"); } final TblAccount account = new TblAccount(); account.setUsername(username); account.setPassword(bCryptEncoder.encode(password)); save(account); return new IMessage(OK, "Successfully created!"); } public IMessage tryAuthenticateUser(Request request, String username, String password) { if (username == null || username.isEmpty() || password == null || password.isEmpty()) { return new IMessage(ERROR, "Invalid request parameters!"); } final UserDetails userDetails = loadUserByUsername(username); if (userDetails == null) { return new IMessage(ERROR, "Account not found!"); } if (!bCryptEncoder.match(password, userDetails.getPassword())) { return new IMessage(ERROR, "Password does not match!"); } securityConfigureAdapter.getContext().authenticate(request, userDetails); return new IMessage(OK, "Successfully authenticated"); } public IMessage logout(Request request) { if (securityConfigureAdapter.getContext().removeAuthInformation(request)) { return new IMessage(OK, "/"); } return new IMessage(ERROR, "Credentials not found or not authenticated!"); } }
** Erklärungen:
Annotation @IoCComponent - dient zum Initialisieren einer Klasse als Komponente.
Annotation @IoCDependency - dient zum Einfügen von Abhängigkeiten in die Klasseninstanz.
Das Dienstprogramm BCryptEncoder ist eine Implementierung des BCrypt-Codecs für die Kennwortverschlüsselung (bisher der einzige Codec).
Systeminstanz SecurityConfigureAdapter - wird verwendet, um mit Zuordnungsanforderungen und Benutzersitzungen zu arbeiten.
Funktion UserDetails loadUserByUsername - geerbte Funktion UserDetailsProcessor , mit der der Benutzer in die Sitzung geladen und das Authentifizierungsflag gesetzt wird (in Zukunft für die Standardzuordnung der Autorisierung in Security ).
Die IMessage-Funktion tryCreateUser ist eine Benutzererstellungsfunktion.
IMessage-Funktion tryAuthenticateUser - Benutzerauthentifizierungsfunktion.
Die IMessage-Abmeldefunktion ist eine Funktion zum Löschen einer Sitzung von einem autorisierten Benutzer.
Die IMessage- Klasse ist eine Dienstprogrammklasse zum Anzeigen der Informationen, die wir im Browser benötigen (JSON-Antwort).
package org.examples.webapp.responces; public class IMessage { private final String message; private final Type type; public IMessage(String message) { this.message = message; type = Type.OK; } public IMessage(Type type, String message) { this.message = message; this.type = type; } public String getMessage() { return message; } public Type getType() { return type; } public enum Type { OK, ERROR } }
Jetzt benötigen Sie die Implementierung des Links selbst (Request Mapping):
package org.examples.webapp.mapping; import org.examples.webapp.domain.entity.TblAccount; import org.examples.webapp.responces.IMessage; import org.examples.webapp.service.AccountService; import org.ioc.annotations.context.IoCDependency; import org.ioc.annotations.web.IoCController; import org.ioc.web.annotations.Credentials; import org.ioc.web.annotations.MappingMethod; import org.ioc.web.annotations.RequestParam; import org.ioc.web.annotations.UrlMapping; import org.ioc.web.model.ModelAndView; import org.ioc.web.model.http.Request; @IoCController @UrlMapping("/") public class MainMapping { @IoCDependency private AccountService accountService; @UrlMapping public ModelAndView index() { final ModelAndView modelAndView = new ModelAndView(); modelAndView.setView("index"); return modelAndView; } @UrlMapping(value = "signup", method = MappingMethod.POST) public IMessage createUser(@RequestParam("username") String username, @RequestParam("password") String password, @RequestParam("repeatedPassword") String repeatedPassword) { return accountService.tryCreateUser(username, password, repeatedPassword); } @UrlMapping(value = "signin", method = MappingMethod.POST) public IMessage auth(Request request, @RequestParam("username") String username, @RequestParam("password") String password) { return accountService.tryAuthenticateUser(request, username, password); } @UrlMapping("signout") public IMessage signout(Request request) { return accountService.logout(request); } @UrlMapping("loginPage") public ModelAndView authenticated(@Credentials TblAccount account) { final ModelAndView modelAndView = new ModelAndView(); modelAndView.setView("auth"); modelAndView.addAttribute("account", account); return modelAndView; } }
** Erklärungen:
Annotation @IoCController - dient dazu, die Klasse im Kontext als Controller zu identifizieren (Browser Request Mapper)
Annotation @UrlMapping - gibt an, dass eine Funktion / Klasse auf das Vorhandensein von Anforderungen analysiert werden muss, die von Channel- Handlern verarbeitet werden.
Parameter:
- Wert - die Anfrage, die wir brauchen;
- Methode - http-Methode zur Verarbeitung (GET, POST, PUT usw.);
- verbraucht - http MIME-Typ, um das Vorhandensein einer Anforderung eines bestimmten Typs zu überprüfen (optional);
- erzeugt - http-Inhaltstyp, um einen bestimmten Inhaltstyp in der Antwort zurückzugeben (Inhaltstyp: text / html; Zeichensatz = utf-8, Inhaltstyp: mehrteilig / Formulardaten; Grenze = etwas usw. optional;
Annotation @RequestParam - dient dazu, den Namen des empfangenen Parameters aus der Anforderung zu bestimmen. Da es unmöglich ist, den aktuellen Namen des Methodenparameters standardmäßig als Reflexionsmittel abzurufen, war ich zu faul, um eine zusätzliche Javaassist-Abhängigkeit mit dem Schamanen mit asm zu verbinden. Daher wird ein solches Verfahren zum Bestimmen des Namens des Parameters zum Einbetten dieser Parameterwerte aus der Anforderung erhalten. Für den GET- Typ gibt es ein Analogon - @PathVariable - das gleiche Funktionsprinzip (nicht kompatibel mit POST ).
Annotation @Credentials - dient zum Einfügen der aktuellen Daten des autorisierten Benutzers. Andernfalls kann sie null sein, wenn sich die Informationen des autorisierten Benutzers nicht in der Sitzung befinden.
Das Request-Klassensystem ist die aktuelle Information über eine eingehende Anfrage, die Coca, Header und einen Benutzerkanal enthält, die später an Push Message's gesendet werden können ... der diesbezüglich bereits eine Art Fantasie hat.
Die Dienstprogrammklasse ModelAndView ist ein Seitenmodell mit dem Namen der Ressource ohne Erweiterung und Attributen zum Einbetten in die Ressource.
Es scheint alles zu sein, aber nein - Sie müssen auf jeden Fall die verfügbare Zuordnung von Anforderungen für Benutzer konfigurieren.
package org.examples.webapp.config; import org.ioc.annotations.configuration.Property; import org.ioc.annotations.configuration.PropertyFunction; import org.ioc.web.security.configuration.HttpContainer; import org.ioc.web.security.configuration.SecurityConfigureProcessor; import org.ioc.web.security.encoder.Encoder; import org.ioc.web.security.encoder.bcrypt.BCryptEncoder; import org.ioc.web.security.filter.CorsFilter; import org.ioc.web.security.filter.CsrfFilter; @Property public class SecurityConfig implements SecurityConfigureProcessor { @Override public void configure(HttpContainer httpContainer) { httpContainer. configureRequests(). anonymousRequests("/", "/signup", "/signin"). resourceRequests("/static/**"). authorizeRequests("/loginPage", "ROLE_USER"). authorizeRequests("/signout", "ROLE_USER"). and(). configureSession(). expiredPath("/"); } @PropertyFunction public CsrfFilter csrfFilter() { return new CsrfFilter(); } @PropertyFunction public CorsFilter corsFilter() { return new CorsFilter(); } @PropertyFunction public Encoder encoder() { return new BCryptEncoder(); } }
** Erklärungen:
@ Property-Annotation - teilt dem Kontext mit, dass dies eine Konfigurationsdatei ist und initialisiert werden muss.
Annotation @PropertyFunction - Informiert den Konfigurationsanalysator, dass diese Funktion einen Typ zurückgibt und ihn als Komponente (bin) initialisieren sollte.
Schnittstelle SecurityConfigureProcessor - ein Dienstprogramm zum Konfigurieren der Zuordnung von Anforderungen.
Die Modellklasse HttpContainer ist ein Dienstprogramm, das die Zuordnung der vom Benutzer angegebenen Anforderungen speichert.
Die CsrfFilter-Klasse ist ein Filter für ungültige Anforderungen (Implementierungen der CSRF-Mechanik).
Die CorsFilter-Klasse ist ein Filter für die gemeinsame Nutzung von Ressourcen.
AnonymousRequests-Funktion - akzeptiert eine unbegrenzte Anzahl von Anforderungen, erfordert keine autorisierten Benutzer und keine Rollenprüfung (ROLE_ANONYMOUS).
Die resourceRequests-Funktion - nimmt eine unbegrenzte Anzahl von Anforderungen auf und dient speziell dazu, zu bestimmen, welcher Pfad die Ressourcendatei sein wird, für den keine komplexe Verarbeitung erforderlich ist (CSS, JS, Bilder usw.).
Funktion authorizeRequests - Nimmt eine unbegrenzte Anzahl von Anforderungen auf, erfordert einen autorisierten Benutzer und die dem Benutzer innewohnende spezifische Rolle.
ExpiredPath-Funktion - Beim Löschen einer Sitzung, die rechtzeitig abgelaufen ist, wird der Benutzer durch diese Zuordnung umgeleitet (Weiterleitungslink).
Nun, es gab Seiten, Skripte und Site-Stile (ich werde nicht tief gehen).
Spoiler Überschriftindex.vm - Hauptseite
<html> <head> <meta charset="utf-8"/> <title>IoC Test</title> <link rel="stylesheet" href="/static/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/css/style.css"/> <link rel="stylesheet" href="/static/css/pnotify.custom.min.css"/> <link rel="stylesheet" href="/static/css/pnotify.css"/> <link rel="stylesheet" href="/static/css/pnotify.buttons.css"/> </head> <body> <div class="container"> <h1>IoC Starter Test</h1> <br> <h4>Create user</h4> <br> <form id="creation"> <label for="username">Username: </label> <input type="text" id="username" name="username" class="color-input-field"/> <label for="password">Password: </label> <input type="password" id="password" name="password" class="color-input-field"/> <label for="repeatedPassword">Repeate: </label> <input type="password" id="repeatedPassword" name="repeatedPassword" class="color-input-field"/> <button type="button" class="btn btn-success btn-create">Sing up!</button> </form> <h4>Authenticate</h4> <br> <form id="auth"> <label for="username">Username: </label> <input type="text" id="username" name="username" class="color-input-field"/> <label for="password">Password: </label> <input type="password" id="password" name="password" class="color-input-field"/> <button type="button" class="btn btn-danger btn-auth">Sing in!</button> </form> </div> <script type="text/javascript" src="/static/js/jquery.js"></script> <script type="text/javascript" src="/static/js/bootstrap.min.js"></script> <script type="text/javascript" src="/static/js/scripts.js"></script> <script type="text/javascript" src="/static/js/pnotify.js"></script> <script type="text/javascript" src="/static/js/pnotify.buttons.js"></script> </body> </html>
auth.vm - um einen autorisierten Benutzer anzuzeigen
<html> <head> <meta charset="utf-8"/> <title>IoC Test</title> <link rel="stylesheet" href="/static/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/css/style.css"/> <link rel="stylesheet" href="/static/css/pnotify.custom.min.css"/> <link rel="stylesheet" href="/static/css/pnotify.css"/> <link rel="stylesheet" href="/static/css/pnotify.buttons.css"/> </head> <body> <div class="container"> <h1>Authorized page</h1> <br> <h4>Test auth data</h4> <div id="auth_data"> #if($!account) <h4>Hello @$!account.username, You successfully authenticated!</h4> <br> <button type="button" class="btn btn-success btn-logout">Logout!</button> #end </div> </div> <script type="text/javascript" src="/static/js/jquery.js"></script> <script type="text/javascript" src="/static/js/bootstrap.min.js"></script> <script type="text/javascript" src="/static/js/scripts.js"></script> <script type="text/javascript" src="/static/js/pnotify.js"></script> <script type="text/javascript" src="/static/js/pnotify.buttons.js"></script> </body> </html>
scripts.js - Controller zum Senden und Empfangen von Anforderungsinformationen an den Server
$(function () { $(".btn-create").click(function () { var cooki = cookie(); document.cookie = 'CSRF-TOKEN=' + cooki; $.ajax({ url: "/signup", data: $('#creation').serialize(), headers: {'X-CSRF-TOKEN': cooki}, crossDomain: true, xhrFields: { withCredentials: true }, type: "POST" }).done(function (data) { switch (data.type) { case 'OK': new PNotify({ title: 'Success', text: data.message, type: 'success', hide: false }); break; case 'ERROR': new PNotify({ title: 'Error', text: data.message, type: 'error', hide: false }); break; } }); }); $(".btn-auth").click(function () { var cooki = cookie(); document.cookie = 'CSRF-TOKEN=' + cooki; $.ajax({ url: "/signin", data: $('#auth').serialize(), headers: {'X-CSRF-TOKEN': cooki}, crossDomain: true, xhrFields: { withCredentials: true }, type: "POST" }).done(function (data) { switch (data.type) { case 'OK': new PNotify({ title: 'Success', text: data.message, type: 'success', hide: false }); setTimeout(function () { window.location = "/loginPage"; }, 5000); break; case 'ERROR': new PNotify({ title: 'Error', text: data.message, type: 'error', hide: false }); break; } }); }); $(".btn-logout").click(function () { $.ajax({ url: "/signout", crossDomain: true, xhrFields: { withCredentials: true }, type: "GET" }).done(function (data) { switch (data.type) { case 'OK': new PNotify({ title: 'Success', text: 'Logouting...', type: 'success', hide: false }); setTimeout(function () { window.location = data.message; }, 5000); break; case 'ERROR': new PNotify({ title: 'Error', text: data.message, type: 'error', hide: false }); break; } }); }); }); function cookie(a) { return a
Kompilieren Sie, führen Sie alles aus, was wir haben.
Wenn alles korrekt ist, sehen wir am Ende des Downloads so etwas:
Protokoll[21.10.18 22: 29: 51: 990] INFO web.model.mapping.MappingContainer: Zugeordnete Methode [/], Methode = [GET] auf [public org.ioc.web.model.ModelAndView org.examples.webapp .mapping.MainMapping.index ()]
[21.10.18 22: 29: 51: 993] INFO web.model.mapping.MappingContainer: Zugeordnete Methode [/ signup], Methode = [POST] auf [public org.examples.webapp.responces.IMessage org.examples. webapp.mapping.MainMapping.createUser (java.lang.String, java.lang.String, java.lang.String)]
[21.10.18 22: 29: 51: 993] INFO web.model.mapping.MappingContainer: Zugeordnete Methode [/ signin], method = [POST] auf [public org.examples.webapp.responces.IMessage org.examples. webapp.mapping.MainMapping.auth (org.ioc.web.model.http.Request, java.lang.String, java.lang.String)]
[21.10.18 22: 29: 51: 993] INFO web.model.mapping.MappingContainer: Zugeordnete Methode [/ signout], method = [GET] auf [public org.examples.webapp.responces.IMessage org.examples. webapp.mapping.MainMapping.signout (org.ioc.web.model.http.Request)]
[21.10.18 22: 29: 51: 995] INFO web.model.mapping.MappingContainer: Zugeordnete Methode [/ loginPage], Methode = [GET] auf [public org.ioc.web.model.ModelAndView org.examples. webapp.mapping.MainMapping.authenticated (org.examples.webapp.domain.entity.TblAccount)]
[21.10.18 22: 29: 51: 997] INFO ioc.web.factory.HttpInitializerFactory: Der HTTP-Server wurde an Port (en) gestartet: 8081 (http)
Ergebnis:
1) Homepage

2) Registrierung

3) Authentifizierung

4) Die Seite mit dem Autorisierungsergebnis (Weiterleitung nach korrekter Eingabe von Login und Passwort)

5) Löschen von Autorisierungsinformationen aus der Sitzung und Weiterleiten des Benutzers zur Startseite

6) Ein Versuch eines nicht autorisierten Benutzers, mit Informationen zur Sitzungsauthentifizierung auf die Seite zu gelangen

Das Ende
Das Projekt entwickelt sich, „Mitwirkende“ und originelle Ideen sind willkommen, da es schwierig ist, dieses Projekt alleine durchzuführen.
Projekt-Repository .
Kontext
ORM Fabrik
Web Factory
Beispiele
Aktuelles Beispiel aus dem Artikel
Auch im Repository gibt es Beispiele für die Verwendung aller Funktionen im Modul "Beispiele". Wie sie sagen: "Viel Glück, viel Spaß", vielen Dank für Ihre Aufmerksamkeit.