gpt4 book ai didi

javascript - React 身份验证 session 管理

转载 作者:太空宇宙 更新时间:2023-11-03 22:20:10 27 4
gpt4 key购买 nike

我正在开发这个由两部分组成的应用程序(React + Express...+ Apollo(用于 GraphQL))。为了管理身份验证,我一直在阅读指南和观看视频,并且使用 JWT token 取得了一些进展。和 Context API像:

  1. 每当用户登录时,React 都会使用 gql 向 Express 发出请求(由 apollo-boost 提供支持)。
  2. Express 服务器(后端)向其发送响应并使用解析器处理其数据:
require('dotenv').config();
import { User } from '../models/User';
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';

export default {
Query: {
login: async (_, { email, password }, {req}) => {
try {
const user = await User.findOne({ email });
if (!user) {
throw new Error('User don\'t exist');
}

const isEqual = await bcrypt.compare(password, user.password);
if (!isEqual) {
throw new Error('Wrong credentials');
}

const {
JWTSECRET = 'secret'
} = process.env;

const token = jwt.sign({ userId: user.id, email: user.email }, JWTSECRET, {
expiresIn: '1h'
});

return {
userId: user.id,
token,
tokenExpiration: 3600000 // Date.now()+3600000 doesn't work cause Int is 32-bit signed
}

} catch (e) {
throw new Error(e.message);
}
}
}
};

const hashPassword = async password => {
const saltRounds = 10;

const hashedPassword = await new Promise((resolve, reject) => {
try {
bcrypt.hash(password, saltRounds, (err, hash) => {
if (err) reject(err);
resolve(hash);
});
} catch (e) {
throw new Error(e.message);
}
});

return hashedPassword;
};
  • React 获取响应并将其附加到上下文,我猜它还会分配一些 localStorage 内容来持久 session ,例如:
  • import React from 'react';
    import AuthContext from './auth-context';
    import ApolloClient, { gql } from 'apollo-boost';

    function getClient() {
    return new ApolloClient({ uri: 'http://localhost:4000/ws', credentials: 'same-origin' });
    }

    const AuthState = props => {
    const defaultValue = {
    userId: null,
    userFirstName: null,
    userLastName: null,
    userEmail: null,
    token: null,
    tokenExpiration: null,
    createdOn: null,
    errors: [],
    login,
    get,
    };

    return (
    <AuthContext.Provider value={defaultValue}>
    {props.children}
    </AuthContext.Provider>
    );

    /**
    * Login
    * @param {string} email
    * @param {string} password
    */
    async function login(email, password) {
    const client = getClient();
    const CHECK_CREDENTIALS = gql`
    query {
    login(email: "${email}", password: "${password}") {
    userId
    token
    tokenExpiration
    }
    }
    `;
    const { data, loading, errors } = await client.query({
    query: CHECK_CREDENTIALS,
    errorPolicy: 'all'
    });

    if (loading) {
    defaultValue.message = "Validating credentials";
    }

    if (errors) {
    defaultValue.errors = errors.map(error => <p>{error.message}</p>);
    }

    if (data && data.login) {
    defaultValue.userId = data.login.userId;
    defaultValue.token = data.login.token;
    defaultValue.tokenExpiration = data.login.tokenExpiration;
    // Persist session ?
    localStorage.setItem('user-token', data.login.token);
    localStorage.setItem('user-token-expiration', data.login.tokenExpiration);
    }
    }

    async function get(userId) {
    const client = getClient();
    const GET_USER = gql`
    query {
    user(_id: "${userId}") {
    firstName
    lastName
    email
    }
    }
    `;

    const { data, loading, errors } = await client.query({
    query: GET_USER,
    errorPolicy: 'all'
    });

    if (loading) {
    defaultValue.message = "Getting user";
    }

    if (errors) {
    defaultValue.errors = errors.map(error => <p>{error.message}</p>);
    }

    if (data && data.user) {
    defaultValue.userFirstName = data.user.firstName;
    defaultValue.userLastName = data.user.lastName;
    defaultValue.userEmail = data.user.email;
    }
    }
    }

    export default AuthState;
  • 在每个需要身份验证的组件中,我都会检查 context.tokencontext.tokenExpiration 并重定向到登录或让它们通过。
  • 我一直想知道如果我使用开发者控制台手动设置一些user-tokenuser-token-expiration会怎样?我错过了什么?

    欢迎任何评论。

    最佳答案

    嗯...我一直在深入研究代码,并验证了 login 解析器使用 secret 签名来验证 token 。

    login: async (_, { email, password }, {req}) => {
    try {
    const user = await User.findOne({ email });
    if (!user) {
    throw new Error('wrong credentials');
    }

    const isEqual = await bcrypt.compare(password, user.password);
    if (!isEqual) {
    throw new Error('wrong credentials');
    }

    const {
    JWTSECRET = 'secret'
    } = process.env;

    const token = jwt.sign({ userId: user.id, email: user.email }, JWTSECRET, {
    expiresIn: '1h'
    });

    return {
    userId: user.id,
    token,
    tokenExpiration: Date.now() + 3600000
    }

    } catch (e) {
    throw new Error(e.message);
    }
    }

    要查看实际情况,请访问 JWT.IO Official page生成 token 后并将其粘贴到那里。然后在验证签名字段中插入“ secret ”或任何内容,它会将无效签名更改为已验证

    关于javascript - React 身份验证 session 管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57627811/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com