Application Web avec IoC Starter. Mappage de requĂȘte de base Ă  l'aide du contexte ioc, du web ioc et de l'orm ioc

image

Présentation


Depuis la premiÚre version, beaucoup de temps s'est écoulé ( lien vers l'article précédent ). Qu'est-ce qui a changé?


  • amĂ©lioration de la stabilitĂ© du systĂšme dans son ensemble;
  • implĂ©mentĂ© le chargement des composants paresseux;
  • SystĂšme d'Ă©coute de base intĂ©grĂ©
  • support intĂ©grĂ© pour la programmation orientĂ©e aspect (pour les problĂšmes de difficultĂ© moyenne, sinon je vous conseille d'utiliser la bibliothĂšque AspectJ)
  • nouveau chargeur de dĂ©marrage RequestFactory
  • travail de cache intĂ©grĂ© basĂ© sur EhCache, Guava
  • le travail avec les flux est intĂ©grĂ© (Ă  la fois l'initialisation via l'annotation @SimpleTask et le travail direct avec le pool)

** Modules


  • module pour travailler avec la base de donnĂ©es (ORM lĂ©ger avec prise en charge de JPA, Transactions, NO-SQL Driver - Orient, mĂ©thodes Crud, systĂšme de rĂ©fĂ©rentiel et requĂȘtes gĂ©nĂ©rĂ©es automatiquement Ă  partir de la fonction de la classe de rĂ©fĂ©rentiel)
  • Module de museau Web (mappage de liens via des annotations, prise en charge des producteurs / consommations personnalisĂ©s, page de rendu des modĂšles Velocity, demandes de sĂ©curitĂ© de base, sessions, cookies, SSL) basĂ© sur Netty 4.1.30.

Structure du cadre
struct


"Bien sûr, tout cela est bon", dites-vous, "mais en fait, cela fonctionne-t-il?"
"Oui, ça marche. Je demande une coupe."


Exemple de processus de mise en Ɠuvre


Pour implémenter l'exemple, j'utiliserai Maven 3 et Intelijj Idea 2018.2.


1) Connectez les dépendances:


<?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> 

** Il n'a pas encore déménagé à Maven Central, hélas.


Structure du projet:
la structure
ModĂšle MVC standard, n'est-ce pas?


Créez un point d'entrée vers l'application:


 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); } } 

** Explications:
Annotation @ScanPackages - définit des packages contextuels pour identifier les composants (dans les personnes ordinaires - "bacs").
Annotation @WebModule - sert Ă  connecter et initialiser une fabrique Web.
Annotation @CacheModule - est utilisé pour connecter et initialiser la fabrique de cache, il est utilisé pour le bon fonctionnement d'ORM (dans les futures versions, une annotation ne sera pas nécessaire).
Annotation @ThreadingModule - est utilisé pour connecter et initialiser une fabrique de threads, il est utilisé pour le bon fonctionnement d'une fabrique Web (dans les versions futures, une annotation ne sera pas nécessaire).
Annotation @DatabaseModule - Utilisé pour connecter et initialiser une fabrique ORM.
Toutes les usines ont des configurateurs par défaut, que vous pouvez changer pour les vÎtres en redéfinissant les fonctions des paramÚtres utilisés par les usines (dans chaque annotation de module, le configurateur de classe est redéfini - Classe <?> AutoConfigurationClass () WebAutoConfiguration.class par défaut ), ou désactivez toute configuration à l'aide de l'annotation @Exclude dans le principal classe.
L'utilitaire IoCStarter est la principale classe d'initialisation de contexte.


Eh bien, tout semble ĂȘtre prĂȘt, le contexte est initialisĂ©, le web fonctionne sur le port par dĂ©faut 8081, mais il n'y a pas de lien, et quand on va sur le site, ça ne nous donne vraiment rien. Bon, continue.


Créons un fichier de configuration pour nos modules. Par défaut, toutes les configurations sont chargées à partir de {rép_travail} /configs/default_settings.properties - nous allons les créer le long du chemin approprié.


 # 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 

Ensuite, nous avons besoin d'une entité utilisateur et de son référentiel de gestion:
Implémentation de l'entité TblAccount:


 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"); } } 

** Explications:
Tout est standard comme avec tous les cadres prenant en charge JPA. Mappez l'entité à l'aide de @ .Entity , créez la clé primaire à l'aide de l'annotation @ .Id , mappez les colonnes à l'aide de l'annotation @Column. et héritez de UserDetails pour identifier l'entité dans le module de sécurité .


Implémentation du référentiel d'entités TblAccountRepository:


 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); } 

** Explications:
Annotation @IoCRepository - sert Ă  dĂ©terminer par contexte que la classe est un rĂ©fĂ©rentiel et doit ĂȘtre traitĂ©e «diffĂ©remment» .
Prend en charge les fonctions CRUD standard:


  • RĂ©cupĂ©ration d'entitĂ© (ID id) - obtient une entitĂ© de type EntitĂ© de la base de donnĂ©es ou du cache par clĂ© primaire;
  • List fetchAll () - rĂ©cupĂšre toutes les entitĂ©s du type Entity, les prĂ©chargeant dans le cache;
  • void save (Entity entity) - crĂ©e / met Ă  jour une entitĂ© de type Entity Ă  la fois dans la base de donnĂ©es et dans le cache;
  • void delete (Entity entity) - supprime une entitĂ© de type Entity de la base de donnĂ©es et du cache;
  • boolĂ©en existe (ID id) - vĂ©rifie si une entitĂ© existe dans la base de donnĂ©es Ă  l'aide de la clĂ© primaire.
    Toutes les demandes CRUD se produisent dans une transaction.

Il prend en charge la gĂ©nĂ©ration automatique de requĂȘtes en remplaçant les fonctions par des mots-clĂ©s, comme dans l'implĂ©mentation ci-dessus ( TblAccount findByUsernameEq (String username) ) et en appelant les requĂȘtes enregistrĂ©es ( NamedQuery )


Fonction findByUsernameEq (String username) - recherche une entité par son champ de nom d'utilisateur . Demande générée:


  select * from tbl_account where username = 'username' 

Ensuite, nous avons besoin d'un niveau pour gérer la logique métier.
Implémentations de AccountService:


 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!"); } } 

** Explications:
Annotation @IoCComponent - sert Ă  initialiser une classe en tant que composant.
Annotation @IoCDependency - sert à injecter des dépendances dans l'instance de classe.
L'utilitaire BCryptEncoder est une implémentation du codec BCrypt pour le cryptage des mots de passe (jusqu'à présent le seul codec).
L'instance systĂšme SecurityConfigureAdapter - est utilisĂ©e pour travailler avec les requĂȘtes de mappage et les sessions utilisateur.
Fonction UserDetails loadUserByUsername - fonction héritée UserDetailsProcessor , sert à charger l'utilisateur dans la session et à définir l'indicateur d'authentification (à l'avenir pour le mappage standard des autorisations dans Security )
La fonction IMessage tryCreateUser est une fonction de création d'utilisateur.
Fonction IMessage tryAuthenticateUser - fonction d'authentification de l'utilisateur.
La fonction de déconnexion IMessage est une fonction permettant d'effacer une session d'un utilisateur autorisé.
La classe IMessage est une classe utilitaire pour afficher les informations dont nous avons besoin dans le navigateur (réponse json).


 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 } } 

Vous avez maintenant besoin de l'implĂ©mentation du lien lui-mĂȘme (mappage des requĂȘtes):


 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; } } 

** Explications:
Annotation @IoCController - sert Ă  identifier la classe dans le contexte en tant que contrĂŽleur (mappeur de demande de navigateur)
Annotation @UrlMapping - indique qu'il est nĂ©cessaire d'analyser une fonction / classe pour la prĂ©sence de requĂȘtes traitĂ©es par les gestionnaires de canaux.
ParamĂštres:


  • valeur - la demande dont nous avons besoin;
  • mĂ©thode - mĂ©thode http pour le traitement (GET, POST, PUT, etc.);
  • consomme - type http mime pour vĂ©rifier la prĂ©sence d'une demande d'un type spĂ©cifique (facultatif);
  • produit - http content-type pour renvoyer un type de contenu spĂ©cifique dans la rĂ©ponse (Content-Type: text / html; charset = utf-8, Content-Type: multipart / form-data; limite = quelque chose, etc. facultatif;

Annotation @RequestParam - sert Ă  dĂ©terminer le nom du paramĂštre reçu Ă  partir de la demande. Puisqu'il est impossible d'obtenir le nom actuel du paramĂštre de mĂ©thode par moyen de rĂ©flexion par dĂ©faut, j'Ă©tais trop paresseux pour connecter une dĂ©pendance javaassist supplĂ©mentaire, Ă  shaman avec asm. Par consĂ©quent, une telle mĂ©thode de dĂ©termination du nom du paramĂštre pour intĂ©grer ces valeurs de paramĂštre obtenues Ă  partir de la demande. Il existe un analogue pour le type GET - @PathVariable - le mĂȘme principe de fonctionnement (non compatible avec POST ).
Annotation @Credentials - sert Ă  insĂ©rer les donnĂ©es actuelles de l'utilisateur autorisĂ©, sinon elle peut ĂȘtre nulle si les informations de l'utilisateur autorisĂ© ne se trouvent pas dans la session.
Le systĂšme de classe de demande est l'information actuelle sur une demande entrante, qui contient de la coca, des en-tĂȘtes et un canal utilisateur, qui peuvent ensuite ĂȘtre envoyĂ©s Ă  Push Message's ... qui a dĂ©jĂ  une sorte de fantaisie Ă  cet Ă©gard.
La classe d'utilité ModelAndView est un modÚle de page avec le nom de la ressource sans extension et des attributs pour l'incorporation dans la ressource.


Il semble que ce soit tout, mais non - vous devez certainement configurer le mappage disponible des demandes pour les utilisateurs.


 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(); } } 

** Explications:
Annotation @Property - indique au contexte qu'il s'agit d'un fichier de configuration et qu'il doit ĂȘtre initialisĂ©.
Annotation @PropertyFunction - informe l'analyseur de configuration que cette fonction renvoie un certain type et doit l'initialiser en tant que composant (bin).
Interface SecurityConfigureProcessor - un utilitaire utilisé pour configurer le mappage des demandes.
La classe de modÚle HttpContainer est un utilitaire qui stocke le mappage des demandes spécifiées par l'utilisateur.
La classe CsrfFilter est un filtre de requĂȘtes non valides (implĂ©mentations de la mĂ©canique CSRF).
La classe CorsFilter est un filtre de partage de ressources d'origine croisée.


Fonction AnonymousRequests - accepte un tableau illimité de demandes, ne nécessite pas d'utilisateurs autorisés et de vérification des rÎles (ROLE_ANONYMOUS).
La fonction resourceRequests - accepte un nombre illimitĂ© de requĂȘtes, sert spĂ©cifiquement Ă  dĂ©terminer le chemin d'accĂšs du fichier de ressources qui ne nĂ©cessite pas de traitement complexe (css, js, images, etc.).
Fonction authorizeRequests - accepte un nombre illimité de demandes, nécessite un utilisateur autorisé et le rÎle spécifique inhérent à l'utilisateur.
Fonction ExpiredPath - lors de la suppression d'une session qui a expiré dans le temps, l'utilisateur est redirigé par ce mappage (lien de redirection).


Eh bien, il y avait des pages, des scripts et des styles de site (je n'irai pas en profondeur).


Cap de spoiler

index.vm - page principale


 <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 - pour afficher un utilisateur autorisé


 <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 - contrĂŽleur, pour envoyer et recevoir des informations de demande au serveur


 $(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 // if the placeholder was passed, return ? ( // a random number from 0 to 15 a ^ // unless b is 8, Math.random() // in which case * 16 // a random number from >> a / 4 // 8 to 11 ).toString(16) // in hexadecimal : ( // or otherwise a concatenated string: [1e7] + // 10000000 + -1e3 + // -1000 + -4e3 + // -4000 + -8e3 + // -80000000 + -1e11 // -100000000000, ).replace( // replacing /[018]/g, // zeroes, ones, and eights with cookie // random hex digits ) } 

Compilez, exécutez tout ce que nous avons.
Si tout est correct, nous verrons quelque chose comme ça à la fin du téléchargement:


Journal

[21.10.18 22: 29: 51: 990] INFO web.model.mapping.MappingContainer: méthode mappée [/], method = [GET], vers [public org.ioc.web.model.ModelAndView org.examples.webapp .mapping.MainMapping.index ()]
[21.10.18 22: 29: 51: 993] INFO web.model.mapping.MappingContainer: méthode mappée [/ signup], method = [POST], vers [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: méthode mappée [/ signin], method = [POST], vers [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: méthode mappée [/ signout], method = [GET], vers [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: méthode mappée [/ loginPage], méthode = [GET], vers [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: le serveur Http a démarré sur le (s) port (s): 8081 (http)


Résultat:
1) Page d'accueil
index
2) Inscription
inscription
3) Authentification
auth
4) La page avec le résultat de l'autorisation (rediriger aprÚs avoir saisi correctement l'identifiant et le mot de passe)
résultat
5) Effacement des informations d'autorisation de la session et redirection de l'utilisateur vers la page de démarrage
image
6) Une tentative d'un utilisateur non autorisé d'accéder à la page avec les informations d'authentification de session
image


La fin


Le projet se développe, les «contributeurs» et les idées originales sont les bienvenus, car il est difficile de faire ce projet seul.
DépÎt de projets .
Contexte
Usine ORM
Usine Web
Des exemples
Exemple actuel de l'article
Dans le référentiel, vous trouverez également des exemples d'utilisation de toutes les fonctionnalités du module «exemples» et, comme on dit, «Bonne chance, amusez-vous», merci à tous pour votre attention.

Source: https://habr.com/ru/post/fr427247/


All Articles