O JWT (JSON Web Token) é um padrão aberto baseado em JSON (RFC 7519) implementado para aprovar reivindicações entre ambientes de aplicativos de rede. O token foi projetado para ser compacto e seguro, especialmente adequado para cenários de assinatura única (SSO) de sites distribuídos. A instrução JWT é geralmente usada para aprovar informações de identidade do usuário autenticadas entre provedores de identidade e provedores de serviços para facilitar a aquisição de recursos do servidor de recursos. Também pode adicionar algumas informações adicionais de declaração necessárias para outra lógica de negócios. O token também pode ser usado diretamente para autenticação ou criptografado.
Geralmente, é muito arriscado expor a API diretamente. Se você não falar sobre mais nada, poderá beber se for atacado diretamente por uma máquina. De um modo geral, um certo nível de permissão deve ser dividido na API e, em seguida, uma autenticação do usuário é feita e a API correspondente é dada ao usuário com base nos resultados da autenticação. Atualmente, existem várias outras soluções principais:
O OAuth é um padrão de autorização aberto que permite que os usuários permitam que aplicativos de terceiros acessem recursos privados (como fotos, vídeos) armazenados pelo usuário em um serviço sem fornecer nome de usuário e senha para aplicativos de terceiros.
O OAuth permite que os usuários forneçam um token em vez de um nome de usuário e senha para acessar dados que armazenam em um provedor de serviços específico. Cada token autoriza um sistema específico de terceiros (por exemplo, um site de edição de vídeo) a acessar um recurso específico (por exemplo, apenas um vídeo em um determinado álbum) dentro de um período específico de tempo (por exemplo, nas próximas 2 horas). Dessa forma, o OAuth permite que os usuários autorizem sites de terceiros a acessar determinadas informações específicas que armazenam em outros provedores de serviços, em vez de todo o conteúdo
O mecanismo de autenticação de cookies é criar um objeto de sessão no servidor para uma solicitação de autenticação e, ao mesmo tempo, criar um objeto de cookie no navegador do cliente; O objeto Cookie é trazido ao cliente para corresponder ao objeto de sessão no servidor para obter gerenciamento de estado. Por padrão, os cookies serão excluídos quando fecharmos o navegador. No entanto, você pode modificar o tempo de expiração do cookie para tornar o cookie válido por um certo período de tempo. A autenticação baseada no método da sessão inevitavelmente pressionará o servidor (armazenamento de memória), não é fácil de expandir (exigindo lidar com sessões distribuídas), ataques de falsificação de solicitação entre sites (CSRF)
1. Comparado com a sessão, ela não precisa ser salva no servidor e não ocupa a sobrecarga da memória do servidor.
2. Estado de apágua e altamente escalável: por exemplo, existem 3 máquinas (A, B, C) para formar um cluster de servidor. Se a sessão existir na máquina A, a sessão só poderá ser salva em um dos servidores. No momento, você não pode acessar as máquinas B e C, porque a sessão não é armazenada em B e C, e o uso de tokens pode verificar a legitimidade da solicitação do usuário. Não há problema em adicionar mais algumas máquinas, então é isso que isso significa.
3. Separação do front-end e suporte ao acesso cruzado.
- A composição do JWT
{ "iss": "JWT Builder", "iat": 1416797419, "exp": 1448333419, "aud": "www.battcn.com", "sub": "[email protected]", "GivenName": "Levin", "Surname": "Levin", "Email": "[email protected]", "Role": ["Admin", "Member"]}Um JWT é na verdade uma string, que consiste em três partes, cabeçalho, carga útil e assinatura (classificada em sequência na figura acima)
JWT Token Generator: https://jwt.io/
- Autenticação de login
- Solicitação de autenticação
Token inválido
Token válido
Existem vantagens e desvantagens. Se é aplicável deve ser considerado claramente, em vez de tecnologia e estilo.
TokenProperties Mapeamento de chave com recursos Application.yml, fácil de usar
@Configuration@ConfigurationProperties (prefix = "Battcn.Security.token") Classe pública TokenProperties { / *** {@link com.battcn.security.model.token.token} Token Tempo de expiração* / Expire Inteiro privado; / *** emissor*/ emissor de string privado; /*** A assinatura usou a chave {@link com.battcn.security.model.token.token}. */ String String SigningKey; / *** {@link com.battcn.security.model.token.token} Atualização Tempo de expiração*/ Inteiro privado refreschexptime; // Solte o conjunto ...} Classe gerada por token
@ComPonentPublic Classe TokenFactory {private final TokenProperties Properties; @Autowired Public TokenFactory (TokenProperties Properties) {this.properties = Properties; } / ** * Use jjwt para gerar token * @param context * @return * / public AccessToken CreateAccessToken (UserContext Context) {opcional.ofnullable (context.getUserName ()). OrelSeStHrow (()-> new ilegalArgumentException ("Criar T token sem usernken") Opcional.ofnullable (context.Getauthorities ()). OrellSethrow (()-> new IllegalargumentException ("O usuário não possui privilégios")); Reivindicações de reivindicações = jwts.claims (). SetSubject (context.getUserName ()); reivindica.put ("scopes", context.getauthorities (). stream (). map (object :: tostring) .Collect (tolist ())); LocalDateTime CurrentTime = localDateTime.now (); String token = jwts.builder () .setClaims (reivindicações) .setissuer (Properties.getissuer ()) .SetissUedAt (date.from (currentTime.atZone (zoneId.systemDefault (). .atZone (zoneId.systemDefault ()). ToInstant ()). devolver o novo AccessToken (token, reivindicações); } / ** * Gere e refresco refreshToken * @param userContext * @return * / Token público CreateRefreshToken (UserContext userContext) {if (stringUtils.isblank (userContext.getUsername))) {lança novo ilegalarGumentExceptEn ("não pode criar (" não pode criar)) {throw namen) {throw newren); } LocalDateTime CurrentTime = LocalDateTime.now (); Reivindicações de reivindicações = jwts.claims (). SetSubject (userContext.getUserName ()); reivindica.put ("scopes", Arrays.aslist (scopes.refresh_token.authority ())); String token = jwts.builder () .setClaims (reivindicações) .setissuer (Properties.getissuer ()) .setId (uuid.randomuuid (). Tostring () .setissuedat (date.from (currenttime.atZone (zoneId.SemeTeFaLeAnt). .PlusMinutes (Properties.getRefreshExptime ())) .atZone (zoneId.systemDefault ()). ToInstant ()). devolver o novo AccessToken (token, reivindicações); }} O arquivo de configuração, incluindo o tempo de validade do token, a chave secreta, pode ser expandida por si só
Battcn: Segurança: Token: Tempo de Excpiração: 10 # Minutos 1440 Refresh-Exp-Tempo: 30 # Minutos 2880 emissor: http://blog.battcn.com Signation-Key: Battcn
WebSecurityConfig é uma configuração -chave da segurança da primavera. Na segurança, podemos basicamente implementar as funções que queremos definir filtros.
@Configuration@EnableWebSecurityPublic Classe WebSecurityConfig estende WebSecurityConfigureRAdApter {public Static Final String token_header_param = "X-Authorization"; public static final string form_based_login_entry_point = "/api/auth/login"; public static final string token_based_auth_entry_point = "/api/**"; public static final string gerencia_token_based_auth_entry_point = "/gerencia/**"; public static final string token_refresh_entry_point = "/api/auth/token"; @AUTOWIRED RestAuthenticationEntryPoint AuthenticationEntryPoint; @Autowired Authentications PrivateCessHandler SuccessHandler; @AUTOWIRED AUTHenticação privadaFailureHandler FailHandler; @AUTOWIRED PRIVADO LOGINATHENTACIDADE LOGINATHENTACIDADE; @Autowired Private TokenauthenticationProvider TokenauthenticationProvider; @Autowired Private Tokenextractor Tokenextractor; @AUTOWIRED AUTHenticação privada Manager AuthenticationManager; LogInProcessingFilter protegido BuildLogInProcessingFilter () lança exceção {filtro LoginProcessingFilter = new LoginProcessingFilter (form_based_login_entry_point, succcesshandler, falha); filtro.setAuthenticationManager (this.authenticationManager); retorno filtro; } Tokenauthentication ProtectedProcessingFilter BuildTokenAuthenticationProcessingFilter () lança Exceção {List <String> list = lists.newArrayList (token_based_auth_entry_point, gerencia_token_based_auth_entry_point); SkippathRequestMatcher Matcher = new SkippathRequestMatcher (List); TokenauthenticationProcessingFilter filtro = novo TokenauthenticationProcessingFilter (FailHandler, Tokenextractor, Matcher); filtro.setAuthenticationManager (this.authenticationManager); retorno filtro; } @Bean @Override public AuthenticationManager AuthenticationManagerBean () lança exceção {return super.authenticationManagerBean (); } @Override Protected void Configure (autenticaçãoManagerBuilder auth) {auth.authentationProvider (LoginauthentationProvider); auth.authenticationProvider (TokenauthenticationProvider); } @Override Protected void Configure (httpsecurity http) lança exceção {http .csrf (). Desabille () // porque está usando JWT, você pode desativar o csrf aqui.ExceptionHandling () .authenticationEntryPoint (this.authenticationEntSoint). .SessionCreationPolicy (sessionCrationPolicy.StatEless) .And () .authorizerequests () .antmatchers (form_based_login_entry_point) .permitall () // login endpoint .antmatchers (token_refresh_entry_point. .authorizerequests () .antmatchers (token_based_auth_entry_point) .authenticated () // API protegido End-Points .antmatchers (gerencia_token_based_auth_entry_point) .hasanyrole (roleenum.admin.name (). .AddfilterBefore (BuildLoginProcessingFilter (), UsernamePasswordAtHenticationFilter.Class) .AddfilterBe antes (BuildTokenAthenticationProcessingFilter (), UsernamePordAthenticationFilter.Class); }}Como o código JWT é simplesmente encapsulado e contém muito conteúdo, apenas os principais fragmentos são publicados no artigo. Se o código completo for necessário, você poderá obtê -lo diretamente do seguinte git
Código deste capítulo (Battcn-jwt-Service): http://xiazai.vevb.com/201801/yuanma/battcn-cloud_jb51.rar
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.