{"id":610,"date":"2024-05-13T06:00:00","date_gmt":"2024-05-13T09:00:00","guid":{"rendered":"https:\/\/adrianosantostreina.com.br\/blog\/?p=610"},"modified":"2024-05-20T15:36:59","modified_gmt":"2024-05-20T18:36:59","slug":"delphi-horse-e-jwt-guia-completo","status":"publish","type":"post","link":"https:\/\/adrianosantostreina.com.br\/blog\/delphi-horse-e-jwt-guia-completo\/","title":{"rendered":"Delphi Horse e JWT: Guia Completo"},"content":{"rendered":"\n<p>No desenvolvimento de aplica\u00e7\u00f5es web modernas, a seguran\u00e7a \u00e9 um componente cr\u00edtico. JSON Web Tokens (JWTs) emergiram como um padr\u00e3o robusto para gerenciar autentica\u00e7\u00e3o e autoriza\u00e7\u00e3o entre cliente e servidor. Este artigo aborda o uso do JWT em aplica\u00e7\u00f5es Delphi utilizando a biblioteca JOSE de Paolo Rossi e o middleware Horse JWT.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p class=\"has-large-font-size\"><strong>Afinal, o que \u00e9 JWT?<\/strong><\/p>\n\n\n\n<p>O uso de JWT (JSON Web Tokens) tem se popularizado como um m\u00e9todo eficiente para gerenciamento de autentica\u00e7\u00e3o e autoriza\u00e7\u00e3o em aplica\u00e7\u00f5es web e m\u00f3veis. H\u00e1 v\u00e1rias raz\u00f5es para sua ado\u00e7\u00e3o, sendo as principais:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. <strong>Simplicidade e Autossufici\u00eancia<\/strong><\/h3>\n\n\n\n<p>JWTs s\u00e3o autossuficientes, contendo todas as informa\u00e7\u00f5es necess\u00e1rias sobre o usu\u00e1rio. Isso inclui quem \u00e9 o usu\u00e1rio (claims de identidade), quais permiss\u00f5es ele possui (claims de autoriza\u00e7\u00e3o) e outros dados necess\u00e1rios. Uma vez que o token \u00e9 emitido, ele pode ser verificado e validado sem a necessidade de acessar novamente o banco de dados ou armazenamento de sess\u00e3o. Isso \u00e9 particularmente \u00fatil em ambientes distribu\u00eddos, como microservi\u00e7os, onde cada servi\u00e7o pode validar o token independentemente.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. <strong>Compacta\u00e7\u00e3o<\/strong><\/h3>\n\n\n\n<p>JWTs s\u00e3o compactos e podem ser facilmente transmitidos atrav\u00e9s de URLs, par\u00e2metros POST, ou cabe\u00e7alhos HTTP. Isso os torna ideais para transmiss\u00f5es em redes onde a largura de banda pode ser uma limita\u00e7\u00e3o, como em dispositivos m\u00f3veis ou em servi\u00e7os que requerem alta performance.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. <strong>Seguran\u00e7a<\/strong><\/h3>\n\n\n\n<p>JWTs oferecem m\u00faltiplas op\u00e7\u00f5es de seguran\u00e7a. Eles podem ser assinados usando um segredo (com HMAC) ou um par de chaves p\u00fablica\/privada (usando RSA ou ECDSA). Isso garante que apenas a parte que possui a chave secreta ou a chave privada pode gerar um token v\u00e1lido. Al\u00e9m disso, \u00e9 poss\u00edvel encriptar todo o token para proporcionar privacidade entre as partes comunicantes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">4. <strong>Desempenho<\/strong><\/h3>\n\n\n\n<p>Ao reduzir a necessidade de ir ao banco de dados para cada opera\u00e7\u00e3o de autentica\u00e7\u00e3o, JWTs ajudam a diminuir a carga no servidor de banco de dados e melhoram a lat\u00eancia geral das solicita\u00e7\u00f5es. Isso pode ser crucial para aplica\u00e7\u00f5es de alto desempenho e alta escalabilidade.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">5. <strong>Facilidade de Uso em Diferentes Dom\u00ednios<\/strong><\/h3>\n\n\n\n<p>JWTs funcionam bem em cen\u00e1rios de Single Sign-On (SSO), pois s\u00e3o facilmente usados entre diferentes dom\u00ednios e aplica\u00e7\u00f5es. Isso os torna uma escolha eficiente para grandes sistemas distribu\u00eddos onde um usu\u00e1rio pode interagir com m\u00faltiplas aplica\u00e7\u00f5es ou servi\u00e7os que necessitam de informa\u00e7\u00f5es de autentica\u00e7\u00e3o compartilhada.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">6. <strong>Padroniza\u00e7\u00e3o e Comunidade<\/strong><\/h3>\n\n\n\n<p>Sendo um padr\u00e3o aberto, JWT \u00e9 apoiado por uma ampla variedade de bibliotecas e frameworks em praticamente todas as linguagens de programa\u00e7\u00e3o e plataformas, garantindo que h\u00e1 amplo suporte e recursos dispon\u00edveis para desenvolvedores.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">7. <strong>Facilidade de Integra\u00e7\u00e3o com Outros Sistemas<\/strong><\/h3>\n\n\n\n<p>Os JWTs podem ser facilmente integrados com sistemas existentes e novos, incluindo APIs de terceiros que suportam autentica\u00e7\u00e3o baseada em token. Isso torna mais simples a expans\u00e3o de servi\u00e7os e a integra\u00e7\u00e3o com ecossistemas maiores.<\/p>\n\n\n\n<p class=\"has-large-font-size\"><strong>Anatomia do JWT<\/strong><\/p>\n\n\n\n<p>A anatomia de um JSON Web Token (JWT) \u00e9 fundamental para entender como ele funciona e como \u00e9 usado em sistemas de autentica\u00e7\u00e3o e autoriza\u00e7\u00e3o. Um JWT \u00e9 dividido em tr\u00eas partes distintas, cada uma codificada em Base64 e separada por pontos (.):<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. <strong>Header<\/strong><\/h3>\n\n\n\n<p>O cabe\u00e7alho do JWT geralmente consiste em dois componentes principais:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>alg<\/strong>: Este \u00e9 o algoritmo de assinatura utilizado. Pode ser, por exemplo, HS256 para HMAC SHA-256 ou RS256 para RSA com SHA-256.<\/li>\n\n\n\n<li><strong>typ<\/strong>: Este campo especifica o tipo do token, que \u00e9 JWT.<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:yaml decode:true \">{\n  \"alg\": \"HS256\",\n  \"typ\": \"JWT\"\n}\n<\/pre><\/div>\n\n\n\n<p>Este cabe\u00e7alho \u00e9 ent\u00e3o codificado em Base64, resultando em uma string que forma a primeira parte do token.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. <strong>Payload<\/strong><\/h3>\n\n\n\n<p>O payload cont\u00e9m as &#8220;claims&#8221; ou afirma\u00e7\u00f5es sobre o sujeito (geralmente um usu\u00e1rio) e outras informa\u00e7\u00f5es necess\u00e1rias. Existem tr\u00eas tipos de claims:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Registered claims<\/strong>: S\u00e3o um conjunto predefinido de claims que n\u00e3o s\u00e3o obrigat\u00f3rias, mas recomendadas. Incluem iss (emissor), exp (tempo de expira\u00e7\u00e3o), sub (assunto do token), aud (audi\u00eancia), entre outros.<\/li>\n\n\n\n<li><strong>Public claims<\/strong>: Podem ser definidas \u00e0 vontade; contudo, para evitar colis\u00f5es, elas devem ser definidas em um registro IANA ou ser definidas como um URI que evita colis\u00f5es.<\/li>\n\n\n\n<li><strong>Private claims<\/strong>: S\u00e3o claims criadas para compartilhar informa\u00e7\u00f5es entre partes que concordam com o uso dessas claims e n\u00e3o s\u00e3o registradas nem p\u00fablicas.<\/li>\n<\/ul>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:yaml decode:true \">{\n  \"sub\": \"1234567890\",\n  \"name\": \"John Doe\",\n  \"admin\": true,\n  \"iat\": 1516239022\n}\n<\/pre><\/div>\n\n\n\n<p>Este payload tamb\u00e9m \u00e9 codificado em Base64, formando a segunda parte do token.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. <strong>Signature<\/strong><\/h3>\n\n\n\n<p>A assinatura \u00e9 usada para verificar se o token n\u00e3o foi alterado. Para criar a assinatura, pega-se o header codificado em Base64, o payload codificado em Base64, e utiliza-se um segredo para assinar esses dados com o algoritmo especificado no cabe\u00e7alho.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Como a assinatura \u00e9 criada:<\/h4>\n\n\n\n<p>Para um cabe\u00e7alho e payload codificados, a assinatura seria gerada como:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:yaml decode:true \">HMACSHA256(\n  base64UrlEncode(header) + \".\" +\n  base64UrlEncode(payload),\n  secret)\n<\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Exemplo de um Token JWT Completo<\/h3>\n\n\n\n<p>Um token pode parecer com isso quando todas as partes s\u00e3o juntas:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:yaml decode:true \">eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.\neyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.\nSflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c\n<\/pre><\/div>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Quebrei as linhas pra ficar mais simples o entendimento. Note que h\u00e1 um ponto ao final de cada linha. Voc\u00ea pode pegar esse JWT e acessar o site <a href=\"https:\/\/jwt.io\">https:\/\/jwt.io<\/a> e colar o conte\u00fado l\u00e1, e o site mostrar\u00e1 cada parte. Elas v\u00e3o se parecer com a imagem abaixo.<\/p>\n<\/blockquote>\n\n\n\n<figure class=\"wp-block-image size-large\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"607\" src=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-13-1024x607.png\" alt=\"\" class=\"wp-image-616\" srcset=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-13-1024x607.png 1024w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-13-300x178.png 300w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-13-768x455.png 768w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-13.png 1241w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A primeira parte <code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9<\/code> \u00e9 o cabe\u00e7alho codificado em Base64.<\/li>\n\n\n\n<li>A segunda parte <code>eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0<\/code> \u00e9 o payload codificado em Base64.<\/li>\n\n\n\n<li>A terceira parte <code>SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c<\/code> \u00e9 a assinatura HMAC SHA-256 do cabe\u00e7alho e do payload usando um segredo.<\/li>\n<\/ul>\n\n\n\n<p>Espero que isso te ajude a entender melhor a estrutura e a fun\u00e7\u00e3o de cada parte de um JWT!<\/p>\n\n\n\n<p class=\"has-large-font-size\"><strong>Como gerar um Token JWT no Horse?<\/strong><\/p>\n\n\n\n<p>Agora que j\u00e1 entendemos o que \u00e9 um JWT, sua import\u00e2ncia a anatomia de um token JWT, podemos partir para a pr\u00e1tica e construir um exemplo pr\u00e1tico de uso no Delphi. N\u00f3s precisaremos basicamente de 02 (duas) bibliotecas, uma delas para gerar o Token e a outra para fazer uso do JWT no Horse. Em uma aplica\u00e7\u00e3o real recomendo que voc\u00ea crie 02 servi\u00e7os, um deles ser\u00e1 uma API Horse para gerar o Token e outra API principal com suas regras de neg\u00f3cios, dessa forma voc\u00ea pode reutilizar a primeira API para qualquer dos seus sistemas se precisar. Entretanto, pra facilitar o entendimento e ficar mais f\u00e1cil de montar o exemplo, faremos isso na mesma API.<\/p>\n\n\n\n<p><em>N\u00e3o entrarei em detalhes sobre a cria\u00e7\u00e3o de uma API Horse, vou tomar como verdade que voc\u00ea j\u00e1 sabe como fazer isso. <\/em><\/p>\n\n\n\n<p>Com um projeto Horse aberto no Delphi vamos iniciar nosso exemplo criando um endpoint <strong>\/token<\/strong> capaz de gerar pra n\u00f3s o <strong>token JWT<\/strong>. Mas antes disso vamos instalar a biblioteca necess\u00e1ria. Ao acessar o site <strong><a href=\"https:\/\/jwt.io\">https:\/\/jwt.io<\/a><\/strong> e clicar no menu <strong>Libraries<\/strong> voc\u00ea ser\u00e1 levado para a p\u00e1gina que cont\u00e9m diversas bibliotecas para gera\u00e7\u00e3o do token em diversas linguagens. Procure por Delphi e encontrar\u00e1 a biblioteca do <strong>Paolo Rossi<\/strong> e ent\u00e3o clique no \u00edcone do GitHub dele para ir direto ao projeto da biblioteca ou <a href=\"https:\/\/github.com\/paolo-rossi\/delphi-jose-jwt\" target=\"_blank\" rel=\"noreferrer noopener\">acesse esse link<\/a>.<\/p>\n\n\n\n<p>Recomendo fortemente que pare alguns instantes para ler a documenta\u00e7\u00e3o, pois h\u00e1 muito mais detalhes do que esse artigo.<\/p>\n\n\n\n<p class=\"has-large-font-size\"><strong>Instalando e gerando o JWT<\/strong><\/p>\n\n\n\n<p>A biblioteca Delphi JOSE e JWT, dispon\u00edvel no <a href=\"https:\/\/github.com\/paolo-rossi\/delphi-jose-jwt\">reposit\u00f3rio do Paolo Rossi<\/a>, facilita a cria\u00e7\u00e3o, a valida\u00e7\u00e3o e a decodifica\u00e7\u00e3o de JWTs em aplica\u00e7\u00f5es Delphi. A utiliza\u00e7\u00e3o b\u00e1sica envolve:<\/p>\n\n\n\n<p>V\u00e1 at\u00e9 a raiz do seu projeto e instale a biblioteca com o Boss conforme exemplo abaixo:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:sh decode:true \">$ boss install github.com\/paolo-rossi\/delphi-jose-jwt<\/pre><\/div>\n\n\n\n<p>Para gerar o token bastaria usar um exemplo como abaixo:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">uses\n  JOSE.Core.JWT,\n  JOSE.Core.Builder;\n\nvar\n  Token: TJWT;\n  CompactToken: string;\nbegin\n  Token := TJWT.Create;\n  try\n    Token.Claims.Issuer := 'your-issuer';\n    Token.Claims.Subject := 'your-subject';\n\n    CompactToken := TJWTBuilder.Create.JWT(Token).SetAlgorithm(HS256).SetKey('your-secret').Compact;\n    \/\/ Utilize CompactToken como necess\u00e1rio\n  finally\n    Token.Free;\n  end;\nend;\n<\/pre><\/div>\n\n\n\n<p>Pra ficar mais profissional, vamos criar um controller e ent\u00e3o registrar um endpoint pra isso.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Para isso, crie uma nova Unit, salve-a como <code>api.controller.token.pas<\/code>, ou o nome que desejar, e vamos codificar conforme abaixo:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">unit api.controller.token;\n\ninterface\n\nuses\n  Horse,\n  System.StrUtils,\n  System.SysUtils,\n  System.Classes,\n  System.JSON,\n  System.Generics.Collections,\n  DateUtils,\n  JOSE.Core.JWT,\n  JOSE.Core.Builder,\n\n  API.Infra.Claims;\n\n\nconst\n  C_SECRET_JWT = 'adrianosantostreina2024';\n\nprocedure Registry;\n\nimplementation\n\nprocedure DoGetToken(Req: THorseRequest; Res: THorseResponse);\nvar\n  LToken: TJWT;\n  LExpiration: TDateTime;\n  LCompactToken: string;\n  LCNPJ: string;\n  LCodLicenca: string;\n  LSerialHD: string;\n  LResult: TJSONObject;\n  LClaims: TCustomClaims;\nbegin\n  LToken := TJWT.Create(TCustomClaims);\n  try\n    Req.Body&lt;TJSONobject&gt;.TryGetValue&lt;string&gt;('cnpj', LCNPJ);\n\n    LClaims := TCustomClaims(LToken.Claims);\n    LClaims.Issuer := 'Meu nome de Empresa';\n    LClaims.CNPJ := LCNPJ;\n    LExpiration := IncMinute(Now, 10);\n    LClaims.Expiration := LExpiration;\n\n    LCompactToken := TJOSE.SHA256CompactToken(C_SECRET_JWT, LToken);\n    LResult := TJSONObject.Create;\n\n    LResult.AddPair('Expiration', FormatDateTime('DD\/MM\/YYYY hh:mm:ss.nnn',  LExpiration));\n    LResult.AddPair('Token', LCompactToken);\n    Res.Send&lt;TJSONObject&gt;(LResult);\n  finally\n    LToken.Free;\n  end;\nend;\n\nprocedure Registry;\nbegin\n  THorse\n    .Post('\/token', DoGetToken);\nend;\n\ninitialization\nRegistry;\n\nend.<\/pre><\/div>\n\n\n\n<p>Deixe-me explirar um pouco sobre o c\u00f3digo. N\u00f3s fizemos os uses necess\u00e1rios incluindo <code>JOSE.Core.JWT<\/code> e <code>JOSE.Core.Buider<\/code> que s\u00e3o units do JOSE, a biblioteca de gera\u00e7\u00e3o de JWT do Paolo Rossi. Declaramos uma constante que vai ficar gravada a chave secreta do nosso Token JWT. Em seguida criamos um m\u00e9todo interno <code>DoGetToken <\/code>para responder no endpoint <code>\/token<\/code> da nossa api.<\/p>\n\n\n\n<p>Em nosso m\u00e9todo declamamos algumas vari\u00e1veis para receber os valores, entre elas <code>LToken <\/code>do tipo <code>TJWT<\/code>. Tamb\u00e9m criamos uma vari\u00e1vel do tipo <code>TCustomClaims<\/code>, j\u00e1 explico o que \u00e9 isso.<\/p>\n\n\n\n<p>Em um token JWT n\u00f3s temos os claims default e tamb\u00e9m podemos criar nossos pr\u00f3prios claims, que s\u00e3o campos dentro do token para armazenamento de informa\u00e7\u00f5es personalizadas, como um CNPJ, nome de usu\u00e1rio, ID da aplica\u00e7\u00e3o ou qualquer coisa que desejar colocar nesse token. Sei que a maioria dos meus alunos e seguidores v\u00e3o me perguntar como criar claims personalizados, por isso ao inv\u00e9s de criar um token simples, j\u00e1 vou ensinar voc\u00ea a criar algo personalizado. \ud83d\ude09<\/p>\n\n\n\n<p class=\"has-large-font-size\"><strong>Criando Claims Personalizados<\/strong><\/p>\n\n\n\n<p>Na documenta\u00e7\u00e3o do <code>Middleware Horse-JWT<\/code> voc\u00ea encontrar\u00e1 mais detalhes sobre isso, por esse motivo n\u00e3o vou detalhar muito essa etapa. Quero apenas que entenda que criaremos uma classe chamada <code>TCustomClaims <\/code>(que pode ser o nome que voc\u00ea desejar) e passar essa classe como par\u00e2metro para o <code>Create <\/code>da classe TJWT, assim ela receber\u00e1 os campos personalizados que vamos criar. Portanto, crie uma nova unit no Delphi, d\u00ea o nome de <code>api.infra.claims.pas<\/code> (ou o nome que preferir) e escreva seu c\u00f3digo como abaixo. N\u00e3o h\u00e1 muito o que explicar, \u00e9 relativamente simples.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">unit api.infra.claims;\n\ninterface\n\nuses\n  System.StrUtils,\n  System.SysUtils,\n  System.Classes,\n\n  JOSE.Core.JWT,\n  JOSE.Types.JSON;\n\ntype\n  TCustomClaims = class(TJWTClaims)\n  strict private\n    function GetCNPJ: string;\n    procedure SetCNPJ(const Value: string);\n  public\n    property CNPJ: string read GetCNPJ write SetCNPJ;\n  end;\n\nimplementation\n\n{ TCustomClaims }\n\nfunction TCustomClaims.GetCNPJ: string;\nbegin\n  Result := TJSONUtils.GetJSONValue('CNPJ', FJSON).AsString;\nend;\n\nprocedure TCustomClaims.SetCNPJ(const Value: string);\nbegin\n  TJSONUtils.SetJSONValueFrom&lt;string&gt;('CNPJ', Value, FJSON);\nend;\n\nend.<\/pre><\/div>\n\n\n\n<p>Declaramos as units necess\u00e1rias, criamos uma classe herdando de <code>TJWTClaims<\/code> e ent\u00e3o declaramos os campos personalizados. Aqui estou simulando que nosso JWT conter\u00e1 o cnpj do cliente que ser\u00e1 passado no body da requisi\u00e7\u00e3o quando requisitarmos o endpoint <code>\/token<\/code>, vamos fazer de conta que esse valor ser\u00e1 obrigat\u00f3rio no endepoint. Por fim codificamos os m\u00e9todos <code>Get <\/code>e <code>Set<\/code>. <\/p>\n\n\n\n<p>Retorne em ent\u00e3o ao arquivo <code>api.controller.token.pas<\/code> e perceba que j\u00e1 estamos pegando o cnpj do cliente do Body da requisi\u00e7\u00e3o.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">Req.Body&lt;TJSONobject&gt;.TryGetValue&lt;string&gt;('cnpj', LCNPJ);<\/pre><\/div>\n\n\n\n<p>Adriano ser\u00e1 que posso enviar essa informa\u00e7\u00e3o no <code>Header <\/code>pra ficar menos exposto poss\u00edvel? Claro, fica seu crit\u00e9rio ou de seu cliente. Aqui vou considerar o uso do Body da requisi\u00e7\u00e3o.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>Ponto importante! <\/strong><\/p>\n\n\n\n<p>\u00c9 <strong>altamente <\/strong>recomendando que a gera\u00e7\u00e3o do Token seja feita em um verbo <strong>POST<\/strong>, por isso perceba que nossa rota est\u00e1 configurada para esse verbo.<\/p>\n<\/blockquote>\n\n\n\n<p>Muito bem. A essa altura do artigo, se voc\u00ea fez tudo direitinho, basta compilar a API, executar e ent\u00e3o fazer a chamada ao endpoint <code>http:\/\/localhost:9000\/token<\/code> enviando um JSON no Body da requisi\u00e7\u00e3o com o cnpj. Sua requisi\u00e7\u00e3o se parecer\u00e1 muito com a imagem abaixo. Copie o token para a mem\u00f3ria, entre no <code>https:\/\/jwt.io<\/code> e cole na \u00e1re de teste.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"566\" src=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-14-1024x566.png\" alt=\"\" class=\"wp-image-624\" srcset=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-14-1024x566.png 1024w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-14-300x166.png 300w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-14-768x424.png 768w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-14.png 1148w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Se tudo correu bem, seu JWT ter\u00e1 a apar\u00eancia abaixo:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"1010\" height=\"426\" src=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-15.png\" alt=\"\" class=\"wp-image-625\" srcset=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-15.png 1010w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-15-300x127.png 300w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-15-768x324.png 768w\" sizes=\"(max-width: 1010px) 100vw, 1010px\" \/><\/figure>\n\n\n\n<p>Isso abre um leque quase infinito de possibilidades. Aqui usamos um CNPJ, mas imagine quais informa\u00e7\u00f5es voc\u00ea poderia implementar aqui?<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/adrianosantos.link\/treinamentos\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"150\" src=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/02\/Banner-Hotmart-1.png\" alt=\"\" class=\"wp-image-222\" srcset=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/02\/Banner-Hotmart-1.png 800w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/02\/Banner-Hotmart-1-300x56.png 300w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/02\/Banner-Hotmart-1-768x144.png 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/a><\/figure>\n\n\n\n<p class=\"has-large-font-size\"><strong>Instalando o middleware Horse-JWT na API<\/strong><\/p>\n\n\n\n<p>At\u00e9 o momento fizemos apenas a gera\u00e7\u00e3o do token, agora precisamos implementar a leitura desse JWT e evitar que as rotas sejam acessadas se o programador n\u00e3o enviar o Token ou ele estiver inv\u00e1lido, expirado, etc. Para isso vamos utilizar o Middleware Horse-JWT que est\u00e1 dispon\u00edvel como middleware oficial no github da HashLoad. Retorne ao terminal do Windows e instale o middleware usando a linha de comando abaixo:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:sh decode:true \">boss install horse-jwt<\/pre><\/div>\n\n\n\n<p>Use a for\u00e7a, leia a documenta\u00e7\u00e3o. No GitHub do middlware tem todas as instru\u00e7\u00f5es, inclusive a parte de gera\u00e7\u00e3o e leitura de claims personalizados. De qualquer forma vou facilitar sua vida por aqui e depois voc\u00ea se aprofunda melhor. Pra simularmos as rotas, criei dois endpoints simples no DPR da nossa API.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">  THorse\n    .Use(Jhonson);\n\n  THorse\n    .Get('\/clientes',\n    procedure (Req: THorseRequest; Res: THorseResponse)\n    begin\n      Res.Send&lt;TJSONObject&gt;(TJSONObject.Create.AddPair('cliente', '123456'))\n    end\n    )\n    .Get('\/version',\n    procedure (Req: THorseRequest; Res: THorseResponse)\n    begin\n      Res.Send&lt;TJSONObject&gt;(TJSONObject.Create.AddPair('Vers\u00e3o API', 'v1.0.0'))\n    end\n    );\n\n  THorse\n    .Listen;<\/pre><\/div>\n\n\n\n<p>O endpoint <code>\/clientes <\/code>vai simular a rota para carregar um cliente. J\u00e1 o endpoint <code>\/version<\/code> simula uma rota que devolve a vers\u00e3o da API, s\u00f3 pra brincarmos depois de &#8220;n\u00e3o exigir JWT&#8221; para alguma rota. Portanto, ser\u00e1 obrigat\u00f3rio enviar o token para \/clientes, mas para \/version n\u00e3o ser\u00e1 obrigat\u00f3rio. Se executarmos agora nossa api novamente e tentarmos acionar o endpoint de clientes, veremos que ele est\u00e1 acess\u00edvel sem enviar um token, vamos agora implementar o uso do middleware JWT.<\/p>\n\n\n\n<p class=\"has-large-font-size\"><strong>Impedindo o acesso a uma rota sem enviar o Token<\/strong><\/p>\n\n\n\n<p>Estamos perto da etapa final, vamos configurar agora para que possamos travar o uso do endpoint caso o desenvolvedor n\u00e3o envie o Token. Adicione a unit <code>Horse.JWT<\/code> ao uses do DPR, em seguida fa\u00e7a uso do middlware como abaixo:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">  THorse\n    .Use(\n      HorseJWT('adrianosantostreina2024',\n      THorseJWTConfig.New\n        .SkipRoutes(['\/version', '\/token']))\n    );<\/pre><\/div>\n\n\n\n<p>Perceba que repetimos a chave secreta e na sequ\u00eancia usamos a classe THorseJWTConfig pra configurar as rotas que ser\u00e3o &#8220;skipadas&#8221;, ou seja, v\u00e3o ignorar o token e poder\u00e3o ser acessadas normalmente. O c\u00f3dido completo do DPR ficou assim:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">program ApiHorseComJWT;\n\n{$APPTYPE CONSOLE}\n\n{$R *.res}\n\nuses\n  Horse,\n  Horse.Jhonson,\n  Horse.JWT,\n  System.SysUtils,\n  System.JSON,\n  api.controller.token in 'controller\\api.controller.token.pas',\n  api.infra.claims in 'infra\\api.infra.claims.pas';\n\nbegin\n  THorse\n    .Use(Jhonson);\n\n  THorse\n    .Use(\n      HorseJWT('adrianosantostreina2024',\n      THorseJWTConfig.New\n        .SkipRoutes(['\/version', '\/token']))\n    );\n\n  THorse\n    .Get('\/clientes',\n    procedure (Req: THorseRequest; Res: THorseResponse)\n    begin\n      Res.Send&lt;TJSONObject&gt;(TJSONObject.Create.AddPair('cliente', '123456'))\n    end\n    )\n    .Get('\/version',\n    procedure (Req: THorseRequest; Res: THorseResponse)\n    begin\n      Res.Send&lt;TJSONObject&gt;(TJSONObject.Create.AddPair('Vers\u00e3o API', 'v1.0.0'))\n    end\n    );\n\n  THorse\n    .Listen;\nend.<\/pre><\/div>\n\n\n\n<p>Expirmente rodar a api, chamar o endpoint sem enviar um Token. Voc\u00ea dever\u00e1 receber a mensagem <code>\"Token not found\"<\/code>. Perfeito, agora rode o endpoint <code>\/token<\/code>, copie o token para a mem\u00f3ria e v\u00e1 at\u00e9 o endpoint <code>\/clientes<\/code> (Aqui estou usando o Postman). Clique na aba <strong>Auth<\/strong>, selecione <strong>Bearer Token<\/strong> e no campo ao lado direito cole o token da nossa api.<\/p>\n\n\n\n<p>Certamente ter\u00e1 o seguinte resultado:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"817\" height=\"443\" src=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-16.png\" alt=\"\" class=\"wp-image-630\" srcset=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-16.png 817w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-16-300x163.png 300w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-16-768x416.png 768w\" sizes=\"(max-width: 817px) 100vw, 817px\" \/><\/figure>\n\n\n\n<p>Em outras palavras, conseguimos acessar o endpoint. Aguarde 10 minutos (tempo que colocamos para expira\u00e7\u00e3o do Token) e tente novamente. O token vai expirar e a mensagem de retorno da api ser\u00e1 <strong>Unauthorized<\/strong>.<\/p>\n\n\n\n<p>Fa\u00e7a o teste tamb\u00e9m na rota <code>\/version<\/code>, ela n\u00e3o precisa de token. Perceba tamb\u00e9m que precisamos adicionar<code> \/token<\/code> em <code>SkipRoutes<\/code>, do contr\u00e1rio, ter\u00edamos que enviar um token pra gerar um token, n\u00e3o seria uma coisa legal.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p class=\"has-large-font-size\"><strong>Lendo os campos personalizados<\/strong><\/p>\n\n\n\n<p>Tenho certeza que deve estar se perguntando: E como pego esse CNPJ enviando encapsulado no Token? R\u00e1, boa pergunta. Sabia que ia perguntar. Essa parte \u00e9 bem f\u00e1cil, precisamos apenas executar algumas mudan\u00e7as no endpoint <code>\/clientes<\/code>, vejamos.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"lang:delphi decode:true \">...\n  THorse\n    .AddCallback(HorseJWT('adrianosantostreina2024', \n                          THorseJWTConfig.New.SessionClass(TCustomClaims)))\n    .Get('\/clientes',\n    procedure (Req: THorseRequest; Res: THorseResponse)\n    var\n      LClaims: TCustomClaims;\n      LCNPJ: string;\n    begin\n      LClaims := Req.Session&lt;TCustomClaims&gt;;\n      LCNPJ := LClaims.CNPJ;\n\n      Res.Send&lt;TJSONObject&gt;(\n        TJSONObject.Create\n          .AddPair('cliente', '123456')\n          .AddPair('CNPJ', LCNPJ)\n      )\n    end\n    )\n...<\/pre><\/div>\n\n\n\n<p>Bom, vamos l\u00e1. Perceba que adicionamos um <code>Clallback<\/code> no registro da rota usado <code>AddCallback<\/code>. Nesse callback usamos <code>HorseJWT<\/code> e o <code>THorseJWTConfig.New.SessionClass(TCustomClaims)<\/code>. Isso far\u00e1 com que tenhamos acesso aos campos personalizados do Token enviado, dessa forma na vari\u00e1vel LClaims conseguimos ter acesso ao CNPJ em <code>LClaims.CNPJ<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/adrianosantos.link\/CursoRESTBasicoAvancado\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"150\" src=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/BannerCursoREST.png\" alt=\"\" class=\"wp-image-637\" srcset=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/BannerCursoREST.png 800w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/BannerCursoREST-300x56.png 300w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/BannerCursoREST-768x144.png 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/a><\/figure>\n\n\n\n<p>Em seguida, criei mais um par de chaves e adicionei o CNPJ lido no json de retorno.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"799\" height=\"472\" src=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-17.png\" alt=\"\" class=\"wp-image-631\" srcset=\"https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-17.png 799w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-17-300x177.png 300w, https:\/\/adrianosantostreina.com.br\/blog\/wp-content\/uploads\/2024\/05\/image-17-768x454.png 768w\" sizes=\"(max-width: 799px) 100vw, 799px\" \/><\/figure>\n\n\n\n<p>Isso \u00e9 legal, porque uma vez lido o claim personalizado, podemos fazer qualquer coisa com ele, tal como: validar se o CNPJ \u00e9 v\u00e1lido, se existe no banco, capturar informa\u00e7\u00f5es sobre o cliente no Database, etc. Imagine as possibilidades?<\/p>\n\n\n\n<p class=\"has-large-font-size\"><strong>Quer aprender um pouco mais?<\/strong><\/p>\n\n\n\n<p>O nosso colega <strong>Vinicius Sanchez<\/strong> gravou um v\u00eddeo super detalhado falando sobre os assunto e tenho certeza que vai agregar muito ao aprendizado que obtivemos aqui. Assista o v\u00eddeo abaixo:<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe title=\"#13 Criando uma API REST com Delphi - Token JWT\" width=\"640\" height=\"360\" src=\"https:\/\/www.youtube.com\/embed\/v40_UgSwRwo?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p class=\"has-large-font-size\"><strong>Conclus\u00e3o<\/strong><\/p>\n\n\n\n<p>O uso de JSON Web Tokens (JWT) em aplica\u00e7\u00f5es Delphi, especialmente quando combinado com o framework Horse, oferece uma solu\u00e7\u00e3o robusta e eficiente para gerenciamento de autentica\u00e7\u00e3o e autoriza\u00e7\u00e3o. A integra\u00e7\u00e3o entre Delphi, uma linguagem poderosa e vers\u00e1til, com o framework Horse, que \u00e9 leve e adequado para desenvolvimento r\u00e1pido de aplica\u00e7\u00f5es web, cria um ambiente de desenvolvimento \u00e1gil e seguro.<\/p>\n\n\n\n<p>JWTs, com sua capacidade de encapsular as credenciais do usu\u00e1rio de forma compacta e segura, s\u00e3o ideais para a comunica\u00e7\u00e3o entre diferentes servi\u00e7os e aplica\u00e7\u00f5es, garantindo que as informa\u00e7\u00f5es do usu\u00e1rio sejam mantidas seguras e consistentes em todas as opera\u00e7\u00f5es. Al\u00e9m disso, a autossufici\u00eancia dos JWTs reduz a necessidade de verifica\u00e7\u00f5es de banco de dados constantes, o que pode melhorar significativamente o desempenho das aplica\u00e7\u00f5es.<\/p>\n\n\n\n<p>O middleware Horse JWT facilita a implementa\u00e7\u00e3o de JWT em aplica\u00e7\u00f5es Delphi, permitindo aos desenvolvedores integrar facilmente autentica\u00e7\u00e3o baseada em token em seus sistemas. Isso n\u00e3o s\u00f3 protege as aplica\u00e7\u00f5es contra acessos n\u00e3o autorizados, mas tamb\u00e9m simplifica o processo de manuten\u00e7\u00e3o e expans\u00e3o dos sistemas.<\/p>\n\n\n\n<p>Em resumo, a combina\u00e7\u00e3o de JWT e Horse em Delphi oferece uma estrat\u00e9gia de autentica\u00e7\u00e3o moderna, segura e eficiente. Ela permite aos desenvolvedores construir aplica\u00e7\u00f5es web que n\u00e3o apenas atendem aos requisitos modernos de seguran\u00e7a digital, mas tamb\u00e9m proporcionam uma experi\u00eancia de usu\u00e1rio \u00e1gil e responsiva. Isso destaca o Delphi como uma excelente escolha para desenvolvimento de aplica\u00e7\u00f5es empresariais e sistemas de larga escala que requerem uma solu\u00e7\u00e3o de autentica\u00e7\u00e3o avan\u00e7ada.<\/p>\n\n\n\n<p>Comunidade no <a href=\"https:\/\/t.me\/AdrianoSantosCommunity\">Telegram<\/a><\/p>\n\n\n\n<p>\ud83d\ude80Comente no campo abaixo \ud83d\udc47\ud83d\udc47\ud83d\udc47 o que achou e qual sua d\u00favida.<\/p>\n\n\n\n<p>Te vejo na pr\u00f3xima<\/p>\n\n\n\n<p>Adriano Santos<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>No desenvolvimento de aplica\u00e7\u00f5es web modernas, a seguran\u00e7a \u00e9 um componente cr\u00edtico. JSON Web Tokens (JWTs) emergiram como um padr\u00e3o robusto para gerenciar autentica\u00e7\u00e3o e autoriza\u00e7\u00e3o entre cliente e servidor. Este artigo aborda o uso do JWT em aplica\u00e7\u00f5es Delphi utilizando a biblioteca JOSE de Paolo Rossi e o middleware Horse JWT.<\/p>\n","protected":false},"author":1,"featured_media":638,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-610","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/610","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/comments?post=610"}],"version-history":[{"count":24,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/610\/revisions"}],"predecessor-version":[{"id":642,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/posts\/610\/revisions\/642"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/media\/638"}],"wp:attachment":[{"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/media?parent=610"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/categories?post=610"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/adrianosantostreina.com.br\/blog\/wp-json\/wp\/v2\/tags?post=610"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}