javascript - Jak ukládat a zpracovávat JWT tokeny na front-endu pomocí fetch a jak je ukládat?
Jsem nový ve vývoji, mám aplikaci pro správu úkolů, ve které používám JWT tokeny k ověření. Můžu to rozchodit na Postmanu, ale nedokázal jsem přijít na to, jak je uložit přes prohlížeč a posílat na server.
Tady je to, co se snažím udělat, aby to fungovalo, ale mimo posluchač událostí se to zobrazuje jako undefined a nemohl jsem uložit token, abych ho později poslal na jinou URL, token posílám do API.
Zde je můj kód front-end app.js pro stránku přihlášení, při přihlášení je uživateli zaslán JWT token:
let inMemoryToken;
const signInForm = document.querySelector( "#sign-in-form" );
signInForm.addEventListener( "submit", ( e ) => {
const email = document.querySelector( "#login-email" ).value;
const password = document.querySelector( "#login-pass" ).value;
e.preventDefault();
console.log( email, password );
fetch( "http://localhost:3000/users/login", {
method: 'post',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify( {
"email": email,
"password": password,
} )
} ).then( res => res.json() )
.then( res => {
console.log( res );
let inMemoryToken = res.token;
console.log( inMemoryToken );
// { Authorization: `Bearer ${ inMemoryToken }`; }
return inMemoryToken;
} );
console.log( inMemoryToken );
return inMemoryToken;
} );
// inMemoryToken = res.body.token[ 0 ];
// let inMemoryToken2 = inMemoryToken;
console.log( inMemoryToken );
Můj back-endový kód pro přihlášení je:
router.post( "/users/login", async ( req, res ) => {
try {
const user = await User.findByCredentials(
req.body.email,
req.body.password
);
const token = await user.generateAuthToken();
res.send( {
user,
token,
} );
} catch ( e ) {
res.status( 400 ).send( {
error: "Catch error",
e,
} );
}
} );
Také, po získání tohoto tokenu, chci ho předat na URL mé úlohy, která je taková:
const TaskForm = document.querySelector( "#add-tasks" );
TaskForm.addEventListener( "submit", ( e ) => {
const task = document.querySelector( '#task' ).value;
e.preventDefault();
console.log( task );
console.log( inMemoryToken );
fetch( "http://localhost:3000/tasks/", {
method: 'get',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json',
'Authorization': 'Bearer ${inMemoryToken}'
},
body: JSON.stringify( {
"Task": task
} )
} ).then( res => res.json() )
.then( res => console.log( res ) );
} );
Snažím se to vyřešit už 3 dny a nedaří se mi to, jakákoliv pomoc by byla velice oceněna.
Odpověď č. 1
Pro ukládání JWT na klientovi máte dvě možnosti: strategie Cookies nebo LocalStorage. Předpokládám, že již víte, co je cookie. LocalStorage je velmi podobný cookie, ale je vylepšený a bez odesílání informací v hlavičkách (viz definice Mozilla Developer), proto se LocalStorage obvykle používá jako perzistentní objekt.
Serverová strana zůstává tak, jak ji už máte. Žádné změny nejsou potřeba.
Ve vašem klientovi budete ve handleru odpovědi přihlášení ukládat do LocalStorage vaši odpověď od backendu, takto:
signInForm.addEventListener( "submit", ( e ) => {
. . .
fetch( "http://localhost:3000/users/login", {
. . .
} ).then( res => res.json() )
.then( res => {
console.log( res );
let inMemoryToken = res.token;
localStorage.setItem('user', JSON.stringify(res));
// 'user' is the generic key to sotre in LocalStorage. You could use any name you want
// Store complete object, so you will be able to access 'user' and 'token' later
Ve vaší úkolové funkci byste měli číst LocalStorage pro váš objekt
const TaskForm = document.querySelector( "#add-tasks" );
TaskForm.addEventListener( "submit", ( e ) => {
const task = document.querySelector( '#task' ).value;
e.preventDefault();
console.log( task );
// ------ This is what you have to add --------
const localstorage_user = JSON.parse(localStorage.getItem('user'))
const inMemoryToken = localstorage_user.token
// -------------------------------------------
console.log( inMemoryToken );
