如何使用 fetch 在前端存储和处理 JWT 令牌,以及如何存储?

Abh*_*oni 4 javascript authentication api node.js jwt

我是开发新手,我有一个任务管理器应用程序,在其中使用 JWT 令牌进行验证,我可以使其在 Postman 上工作,但我不知道如何通过浏览器存储它并将其发送到服务器。

这是我试图使其工作的方法,但它在事件侦听器之外显示未定义,并且我无法存储令牌以便稍后将其发送到另一个网址,我正在将令牌发送到 API。

这是我的前端 app.js 代码,用于登录页面,登录时向用户发送 JWT 令牌:

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 );
Run Code Online (Sandbox Code Playgroud)

我的登录后端代码是:

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,
        } );
    }
} );
Run Code Online (Sandbox Code Playgroud)

另外,获得此令牌后,我想将其传递给我的任务 url,如下所示:

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 ) );
} );

Run Code Online (Sandbox Code Playgroud)

我三天以来一直在尝试解决这个问题,但无法让它发挥作用,任何帮助将不胜感激。

小智 7

要在客户端上存储 JWT,您有两个选择:CookiesLocalStorage策略。我想您已经知道 cookie 是什么了。LocalStorage 与 cookie 非常相似,但经过增强并且无需在标头中发送信息(请参阅Mozilla 开发人员定义),这就是 LocalStorage 通常作为持久对象应用的原因。

服务器端保持原样。无需更改。

在您的客户端上,在登录响应的处理程序中,您将在 LocalStorage 中存储来自后端的响应,如下所示:

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
Run Code Online (Sandbox Code Playgroud)

在您的任务函数中,您应该为您的对象阅读 LocalStorage

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 );

Run Code Online (Sandbox Code Playgroud)