JWT (JSON Web Token) est une norme ouverte basée sur JSON (RFC 7519) implémentée pour faire passer les réclamations entre les environnements d'application réseau. Le jeton est conçu pour être compact et sécurisé, particulièrement adapté aux scénarios de connexion unique (SSO) de sites distribués. L'instruction JWT est généralement utilisée pour transmettre des informations d'identité utilisateur authentifiées entre les fournisseurs d'identité et les fournisseurs de services afin de faciliter l'acquisition de ressources à partir du serveur de ressources. Il peut également ajouter des informations de déclaration supplémentaires nécessaires à d'autres logiques commerciales. Le jeton peut également être utilisé directement pour l'authentification ou chiffré.
Habituellement, il est très risqué d'exposer directement l'API. Si vous ne parlez de rien d'autre, vous pouvez le boire si vous êtes directement attaqué par une machine. D'une manière générale, un certain niveau d'autorisation doit être divisé en API, puis une authentification de l'utilisateur est effectuée, et l'API correspondante est donnée à l'utilisateur en fonction des résultats d'authentification. À l'heure actuelle, il existe plusieurs solutions plus traditionnelles:
OAuth est une norme d'autorisation ouverte qui permet aux utilisateurs d'autoriser les applications tierces à accéder aux ressources privées (telles que des photos, des vidéos) stockées par l'utilisateur sur un service sans fournir de nom d'utilisateur et de mot de passe aux applications tierces.
OAuth permet aux utilisateurs de fournir un jeton au lieu d'un nom d'utilisateur et d'un mot de passe pour accéder aux données qu'ils stockent dans un fournisseur de services spécifique. Chaque jeton autorise un système tiers spécifique (par exemple, un site Web d'édition vidéo) pour accéder à une ressource spécifique (par exemple, juste une vidéo dans un certain album) dans un délai spécifique (par exemple, dans les 2 prochaines heures). De cette façon, OAuth permet aux utilisateurs d'autoriser des sites Web tiers pour accéder à certaines informations spécifiques qu'ils stockent dans d'autres fournisseurs de services, plutôt que tout le contenu
Le mécanisme d'authentification des cookies est de créer un objet de session sur le serveur pour une demande d'authentification, et en même temps créer un objet cookie sur le navigateur du client; L'objet Cookie est amené au client pour correspondre à l'objet de session sur le serveur pour réaliser la gestion de l'état. Par défaut, les cookies seront supprimés lorsque nous fermerons le navigateur. Cependant, vous pouvez modifier l'heure d'expiration du cookie pour que le cookie valide pendant une certaine période. L'authentification basée sur la méthode de session mettra inévitablement une certaine pression sur le serveur (stockage de mémoire), pas facile à développer (nécessitant de gérer les séances distribuées), les attaques de contrefaçon de demande croisée (CSRF)
1. Comparé à la session, il n'a pas besoin d'être enregistré sur le serveur et n'occupe pas les frais généraux de mémoire du serveur.
2. Si la session existe sur la machine A, la session ne peut être enregistrée que sur l'un des serveurs. Pour le moment, vous ne pouvez pas accéder aux machines B et C, car la session n'est pas stockée sur B et C, et l'utilisation de jetons peut vérifier la légitimité de la demande de l'utilisateur. C'est normal pour moi d'ajouter quelques machines supplémentaires, c'est donc ce que cela signifie.
3. Séparation frontale et accès croisé dans le domaine croisé.
- La composition de JWT
{"ISS": "Jwt Builder", "IAT": 1416797419, "EXP": 1448333419, "AUD": "www.battcn.com", "sub": "[email protected]", "Girename": "Levin", "nom de famille": "Lenin", "Courriel": " "[email protected]", "rôle": ["admin", "membre"]}Un JWT est en fait une chaîne, qui se compose de trois parties, de l'en-tête, de la charge utile et de la signature (triée en séquence dans l'image ci-dessus)
Générateur de jetons JWT: https://jwt.io/
- Authentification de connexion
- Demande d'authentification
Jeton non valide
Jeton valide
Il y a des avantages et des inconvénients. La question de savoir si elle est applicable devrait être considérée clairement, plutôt que la technologie et le style.
TokenProperties Key Mapping avec application.yml Resource, facile à utiliser
@ Configuration @ configurationProperties (prefix = "battcn.security.token") classe publique tokenproperties {/ ** * {@link com.battcn.security.model.token.token} Temps d'expiration du token * / private Integer ExpirationTime; / ** * émetteur * / émetteur de chaînes privées; / ** * Signature a utilisé Key {@link com.battcn.security.model.token.token}. * / Private String SigningKey; / ** * {@link com.battcn.security.model.token.token} Temps d'expiration de rafraîchissement * / Rafreshaxtime entier privé; // soyez défini ...} Classe générée par jeton
@ComponentPublic Class TokenFactory {Propriétés privées finales de tokenproperties; @Autowired Public TokenFactory (TokenProperties Properties) {this.properties = propriétés; } / ** * Utilisez JJWT pour générer des jetons * @param context * @return * / public AccessToken CreateAccessToken (UserContext Context) {facultatif.ofNullable (context.getUsername ()). OrelSethrow (() -> new illégalargumentException ("Impossible de créer un token sans usinge")); Facultatif.ofNullable (context.getAuthorities ()). OrelSethrow (() -> new illégalArgumentException ("l'utilisateur n'a aucun privilège")); Réclame les affirmations = jwts.claims (). SetSubject (context.getUserName ()); revendication.put ("Scopes", context.getAuthorities (). Stream (). Map (objet :: toString) .Collect (tolist ())); LocalDateTime currentTime = localDateTime.now (); String token = jwts.builder () .setClaims (réclamation) .Settissuer (Properties.getSiner ()) .SetEtUedat (Date.From (actuel .AtZone (ZoneId.SystemDefault ()). ToInstant ())) .signWith (Signaturalgorithm.HS512, Properties.getSignInKey ()) .Compact (); retourner New AccessToken (Token, réclamation); } / ** * générer et rafraîchir RefreshToken * @param userContext * @return * / public token createrefreshtoken (userContext userContext) {if (stringUtils.isblank (userContext.getUsername ()))) {throw new illégalargumentException ("ne peut pas créer de token sans nom d'usage"); } LocalDateTime currentTime = localDateTime.now (); Réclame des revendications = jwts.claims (). SetSubject (userContext.getUsername ()); revendication.put ("Scopes", arrays.aslist (Scopes.Refresh_Token.Authority ())); String token = jwts.builder () .setClaims (réclamation) .Settissuer (Properties.getSiner ()) .SetIdat (uUid.randomuuid (). ToString ()) .SetSeudat (date.from (actuel .PlusMinutes (Properties.getRefreshexptime ())) .AtZone (ZoneId.SystemDefault ()). Toinstant ())) .signWith (Signaturalgorithm.HS512, Properties.getSigningKey ()) .Compact (); retourner New AccessToken (Token, réclamation); }} Le fichier de configuration, y compris le temps d'expiration des jetons, la clé secrète, peut être élargi par lui-même
BATTCN: Sécurité: Token: Temps d'expiration: 10 # Minutes 1440 Refresh-Exp-Time: 30 # Minutes 2880 Émetteur: http://blog.battcn.com Signing-Key: Battcn
WebSecurityConfig est une configuration clé de Spring Security. En sécurité, nous pouvons essentiellement implémenter les fonctions que nous voulons en définissant des filtres.
@ Configuration @ activerwebsEBurityPublic class WebSeCurityConfig étend WebSecurityConfigurerAdapter {public static final String token_header_param = "x-authorisation"; public static final String form_based_login_entry_point = "/ api / auth / ligin"; public static final String token_based_auth_entry_point = "/ api / **"; Public Static Final String manage_token_based_auth_entry_point = "/ manage / **"; public static final String token_refresh_entry_point = "/ api / auth / token"; @Autowired private RestauthenticationEntryPoint AuthenticationEntryPoint; @Autowired Private AuthenticationsUccessHandler SuccessHandler; @Autowired Private AuthenticationFailureHandler FAILSHANDLER; @Autowired LoginAuthenticationProvider LoginAuthenticationProvider; @Autowired Private TokenauthenticationProvider tokenauthenticationProvider; @Autowired Private Tokenextractor Tokenextractor; @Autowired Private AuthenticationManager AuthenticationManager; Protégé LoginProcessingFilter BuildLoginProcessingFilter () lève une exception {LoginProcessingFilter Filter = new LoginProcessingFilter (form_based_login_entry_point, SuccessHandler, échecHandler); filter.setAuthenticationManager (this.authenticationManager); filtre de retour; } protégé TokenauthenticationProcessingFilter buildTokenAuthenticationProcessingFilter () lève exception {list <string> list = lists.newarraylist (token_based_auth_entry_point, manage_token_based_auth_entry_point); SkippathRequestmatcher Matcher = new SkippathRequestMatcher (liste); TokenauthenticationProcessingFilter Filter = new TokenauthenticationProcessingFilter (échechandler, tokenextractor, Matcher); filter.setAuthenticationManager (this.authenticationManager); filtre de retour; } @Bean @Override public AuthenticationManager AuthenticationManagerBean () lève une exception {return super.authenticationManagerBean (); } @Override Protected void configure (AuthenticationManagerBuilder Auth) {Auth.AuthenticationProvider (LoginAuthenticationProvider); auth.authenticationProvider (tokenauthenticationProvider); } @Override Protected void Configure (httpSecurity http) lève une exception {http .csrf (). Disable () // Parce qu'il utilise JWT, vous pouvez désactiver CSRF ici.ExceptionHandling () .AuthenticationEntryPoint (this.authenticationEntryPoint) .and () .SessionManation (). .SessionCreationPolicy (SessionCreationPolicy.Stateless) .And () .AuthorizeRequests () .Antmatchers (Form_Based_Login_entry_Point) .permitall () // Login End-point .antmatchers (token_refresh_entry_point) .Permital .AuthorizeRequests () .antmatchers (token_based_auth_entry_point) .Authenticated () // Protected API Point. .adddFilterBefore (buildLoginProcessingFilter (), usernamepasswordAuthenticationFilter.class) .AddFilterBefore (buildTokenAuthenticationProcessingFilter (), userNamepasswordAuthenticationFilter.class); }}Étant donné que le code JWT est simplement encapsulé et contient beaucoup de contenu, seuls les fragments principaux sont publiés dans l'article. Si le code complet est nécessaire, vous pouvez l'obtenir directement à partir du GIT suivant
Code de ce chapitre (Battcn-jwt-Service): http://xiazai.vevb.com/201801/yuanma/battcn-cloud_jb51.rar
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.