Abkürzung für JSON Web Token.
Weitere Informationen finden Sie unter dem folgenden Link. https://openid-foundation-japan.github.io/draft-ietf-oauth-json-web-token-11.ja.html
Es besteht aus drei Teilen, einem Header, einer Nutzlast und einer Signatur, die jeweils in Base64 codiert sind.
Header
{
"typ":"JWT",
"alg":"HS256"
}
Nutzlast
{
"sub": "1234567890",
"iss": "John Doe",
"aud": "audience",
"exp": 1353604926
}
Unterschrift
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
Die drei Teile sind durch einen Punkt verbunden.
Wenn Sie einfach einen Header, eine Nutzlast und einen Proof erstellen möchten, können Sie dies über den folgenden Link tun. https://jwt.io/#debugger
JWT
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyIiwic3ViIjoidGVzdCIsImF1ZCI6ImF1ZGllbmNlIiwicGFyYW1zIjoie1wiZW1haWxcIjogXCJ0ZXN0QGdtYWlsLmNvbVwiLCBcInBhc3N3b3JkXCI6IFwicGFzc3dvcmRcIn0iLCJleHAiOiIxNTkzODM2ODA2In0.4fC4yLEmYTjiwaXk3R_AUUPEQSuI_ARmkoMqosWEJ-c
Ein JWT-Anspruchssatz ist ein JSON-Objekt, dessen Mitglied ein als JWT gesendeter Anspruch ist. Der Anspruchsname im JWT-Anspruchssatz muss eindeutig sein. Dieses Mal werde ich die folgenden vier Ansprüche verwenden.
"iss" (Emittent) Claim: JWT-Emittenten-ID "sub" (Betreff) Anspruch: Kennung des Betreffs, der Gegenstand von JWT ist Anspruch "aud" (Zielgruppe): Liste der Kennungen von Entitäten, die JWT verwenden sollen "exp" (Ablaufzeit): JWT-Ablaufdatum
Es handelt sich um eine Implementierung der Signaturüberprüfung zum Erkennen von Manipulationen an Anforderungsparametern. Versuchen wir eine Implementierung, die der Nutzlast einen Anforderungsparameter hinzufügt und überprüft, ob der Parameter und der tatsächlich empfangene Parameter manipuliert wurden.
Parameter zur Nutzlast hinzugefügt
"params": "{\"email\":\"[email protected]\",\"password\":\"password\"}",
console
$ rails new jwt --api
gem 'jwt'
app/controllers/concerns/signature.rb
module Signature
extend ActiveSupport::Concern
def verify_signature
render status: 401, json: { message: 'Manipulationen wurden gefunden.'} if request.headers['jwt-signature'].blank?
request_params = JSON.parse(request.body.read)
@signature ||= JwtSignature.new(jwt: request.headers['jwt-signature'])
@signature.verify!(params: request_params)
rescue JwtSignature::InvalidSignature
render status: 401, json: { message: 'Manipulationen wurden gefunden.'}
end
end
app/models/jwt_signature.rb
class JwtSignature
class InvalidSignature < StandardError; end
ALGORITHM = 'HS256'
ISSUER = 'user'
AUDIENCE = 'audience'
SUB = "test"
TOKEN_TYPE = 'JWT'
# SECRET_KEY ist wichtig, definieren Sie es also für jede Umgebung und verwalten Sie es sicher ~
SECRET_KEY = '1gCi6S9oaleH22KWaXyXZAQccBx4lUQi'
def initialize(jwt:)
@jwt = jwt
end
def verify!(params:)
raise InvalidSignature unless valid_payload? && valid_params?(params: params) && valid_header?
end
private
def valid_payload?
return false unless jwt_payload['iss'] == ISSUER
return false unless jwt_payload['sub'] == SUB
return false unless jwt_payload['aud'] == AUDIENCE
true
end
def valid_header?
return false unless jwt_header['alg'] == ALGORITHM
return false unless jwt_header['typ'] == TOKEN_TYPE
true
end
def valid_params?(params:)
JSON.parse(jwt_payload['params']) == params
end
def jwt_header
@jwt_header ||= decoded_jwt.second
end
def jwt_payload
@jwt_payload ||= decoded_jwt.first
end
def decoded_jwt
@decoded_jwt ||= JWT.decode(@jwt, SECRET_KEY, true, algorithm: ALGORITHM)
rescue JWT::DecodeError
raise InvalidSignature
end
end
JWT.decode gibt ein Array von Hash zurück Holen Sie sich Payload mit decoded_jwt.first und Header mit decoded_jwt.second
app / models / user.rb wird generiert
$ rails g model User name:string email:string token:string expired_at:datetime
$ rails db:migrate
routes.rb
Rails.application.routes.draw do
post 'tokens/create'
end
tokens_controller.rb
class TokensController < ActionController::API
include Signature
#Überprüfen Sie die Signaturüberprüfung nur beim Erstellen
before_action :verify_signature, only: %i(create)
def create
#Diesmal ist nur der Signaturüberprüfungsprozess implementiert
user = User.find_by(email: params[:email], password: params[:password])
return render status: 400, json: { message: 'Benutzer existiert nicht.' } unless user
#Aktualisieren, wenn kein Token vorhanden ist
if user.token.blank?
user.token = SecureRandom.uuid
user.save
end
render status: 200, json: { name: user.name, email: user.email, token: user.token }
end
end
$rails c
irb(main):001:0> User.new(name: 'test', email: '[email protected]', password: 'password')
(0.5ms) SELECT sqlite_version(*)
=> #<User id: nil, name: "test", email: "[email protected]", password: [FILTERED], token: nil, expired_at: nil, created_at: nil, updated_at: nil>
irb(main):002:0> User.new(name: 'test', email: '[email protected]', password: 'password').save
(0.1ms) begin transaction
User Create (0.9ms) INSERT INTO "users" ("name", "email", "password", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["name", "test"], ["email", "[email protected]"], ["password", "password"], ["created_at", "2020-07-04 02:30:17.701626"], ["updated_at", "2020-07-04 02:30:17.701626"]]
(0.8ms) commit transaction
=> true
https://jwt.io/#debugger Generieren Sie JwtEncoded-Daten über den obigen Link Der Payload-Teil fügt Jwt-Ansprüche und -Parameter hinzu, die Sie benötigen Hinzufügen von E-Mail und Passwort zu Parametern, um die API-Parameter Json und Payload Json zu vergleichen Ändern Sie den Sicherheitsschlüssel von VERIFY SIGNATURE in Ihre eigene Sicherheit (mithilfe von SECRET_KEY des JwtSignature-Modells). Stellen Sie die Unix-Zeit auf exp ein, wenn Sie die Laufzeit festlegen möchten
unixtime(5 Minuten nach der aktuellen Zeit)
irb(main):040:0> (Time.now + 300).to_i
=> 1593838401
Fügen Sie "jwt-Signatur" zum Header hinzu und fügen Sie JwtEncoded-Daten hinzu
JwtEncodierte Daten
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyIiwic3ViIjoidGVzdCIsImF1ZCI6ImF1ZGllbmNlIiwicGFyYW1zIjoie1wiZW1haWxcIjogXCJ0ZXN0QGdtYWlsLmNvbVwiLCBcInBhc3N3b3JkXCI6IFwicGFzc3dvcmRcIn0iLCJleHAiOiIxNTkzODM4NDAxIn0.dSNqdhHBJKUJHnJa_2sS_3Qr4oNNdr5MKFx5ufwqLv4
E-Mail und Passwort zu Body im JSON-Format hinzugefügt
json
{ "email": "[email protected]", "password": "password"}
Nachdem ich die Signatur überprüft hatte, konnte ich das Token sicher erhalten ~
Da für exp 5 Minuten festgelegt wurden, schlug die Signaturüberprüfung nach 5 Minuten fehl.
Recommended Posts