Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 03.07.2025, 10:29
Аспирант
Отправить личное сообщение для riaron86 Посмотреть профиль Найти все сообщения от riaron86
 
Регистрация: 27.11.2021
Сообщений: 94

Проблема с jwt
прошел курс по разработке интернет магазина на reacr node express postgress (sequelize)
В конце препод все разжевывает но учащимся надо самим создать модуль корзины. Столкнулся со следующей проблемой, чтобы получить все устройства добавленные в корзину надо знать userId кототрый содержится в jwt token-е, для чего я импортирую userController в basketController чтобы расшифровать токен и вытянуть userId, но при импорте авторизация перестает работать что делать вот код:
UserController.js
const ApiError = require('../error/ApiError');
const bcrypt = require('bcrypt')
const jwt = require('jsonwebtoken')
const {User, Basket} = require('../models/models')

const generateJwt = (id, email, role) => {
    return jwt.sign(
        {id, email, role},
        process.env.SECRET_KEY,
        {expiresIn: '24h'}
    )
}

class UserController {
    async registration(req, res, next) {
        const {email, password, role} = req.body
        if (!email || !password) {
            return next(ApiError.badRequest('Некорректный email или password'))
        }
        const candidate = await User.findOne({where: {email}})
        if (candidate) {
            return next(ApiError.badRequest('Пользователь с таким email уже существует'))
        }
        const hashPassword = await bcrypt.hash(password, 5)
        const user = await User.create({email, role, password: hashPassword})
        const basket = await Basket.create({userId: user.id})
        const token = generateJwt(user.id, user.email, user.role)
        return res.json({token})
    }

    async login(req, res, next) {
        const {email, password} = req.body
        const user = await User.findOne({where: {email}})
        if (!user) {
            return next(ApiError.internal('Пользователь не найден'))
        }
        let comparePassword = bcrypt.compareSync(password, user.password)
        if (!comparePassword) {
            return next(ApiError.internal('Указан неверный пароль'))
        }
        const token = generateJwt(user.id, user.email, user.role)
        return res.json({token})
    }

    async check(req, res, next) {
        const token = generateJwt(req.user.id, req.user.email, req.user.role)
        return res.json({token})
    }
}

module.exports = new UserController()


basketController.js
const uuid = require('uuid')
const path = require('path');
const {Users,Basket, BasketDevice, User, Device} = require('../models/models')
const ApiError = require('../error/ApiError');
const {where} = require("sequelize");
const userController = require('./userController')
const jwt = require('jsonwebtoken')

class BasketController {
    async create(req, res, next) {
        try {
            let {deviceId} = req.body
            const generateJWT=userController.check;
            let usrId;
            jwt.verify(generateJWT,process.env.SECRET_KEY, function(err, decoded) {
                usrId=decoded[0];
            });
            const basket = await Basket.findOne({where: {userId:usrId}});

            const basketDevice = await BasketDevice.create({basketId: basket.id,deviceId:deviceId });
                return res.json(basket.id,basketDevice);
        } catch (e) {
            next(ApiError.badRequest(e.message))
        }

    }

    async getAll(req, res) {
        let usrId;
        const generateJWT=userController.check;

        jwt.verify(generateJWT,process.env.SECRET_KEY, function(err, decoded) {
            usrId=decoded[0];
        });
        const basket = await Basket.findOne({where: {userId:usrId}});
        const  basketDevices = await BasketDevice.findAndCountAll({where: {basketId:basket.id}});
        const bdevices={};
        basketDevices.map((bd)=>(
            bdevices.push(Devices.findOne({where: {id:bd.deviceId}}))
    ));
        return res.json(bdevices)
    }


}

module.exports = new BasketController()
Ответить с цитированием
  #2 (permalink)  
Старый 03.07.2025, 10:52
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,276

Твой вариант
Сообщение от riaron86
let usrId;
jwt.verify(generateJWT,process.env.SECRET_KEY, function(err, decoded) {
	usrId=decoded[0];
});
Не рабочий, т.к. асинхронный по природе...
Предложу такой вариант
const usrId = await getId(jwt, generateJWT, process.env.SECRET_KEY)

Ну и сама функция...
// Получить ID пользователя
function getId(jwt, gen, key) {
	return new Promise((res, rej) => {
		jwt.verify(gen, key, (err, decoded) => {
			if (err) return rej(err)
			res(decoded[0])
		});
	})
}
Ответить с цитированием
  #3 (permalink)  
Старый 03.07.2025, 11:14
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,826

ksa, сигнатура метода verify:
jwt.verify(token, secretOrPublicKey, [options, callback])

Там метод/функция генерирующий новый токен нафиг не нужен.
Ответить с цитированием
  #4 (permalink)  
Старый 03.07.2025, 11:18
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,276

Сообщение от Nexus
Там метод/функция генерирующий новый токен нафиг не нужен.
По его коду, он так ИД пользователя получает...
Но с таким синтаксисом присваивание сработает только после завершения всего метода create...

На это я и обратил его внимание. Не более того...
Ответить с цитированием
  #5 (permalink)  
Старый 03.07.2025, 11:25
Аспирант
Отправить личное сообщение для riaron86 Посмотреть профиль Найти все сообщения от riaron86
 
Регистрация: 27.11.2021
Сообщений: 94

выдает ту же ошибку, если делать по примеру ksa.(без импорта userController в basketController код полностью рабочий как вытянуть токен из user controller не сбивая его работу?)
←→1 of 3 errors on the page
Unhandled Rejection (TypeError): Cannot read properties of undefined (reading 'data')
click
C:/online-store-full-course-master/client/src/pages/Auth.js:32
29 | user.setIsAuth(true)
30 | history.push(SHOP_ROUTE)
31 | } catch (e) {
> 32 | alert(e.response.data.message)
| ^ 33 | }
34 |
35 | }

вот сам auth.js
import React, {useContext, useState} from 'react';
import {Container, Form} from "react-bootstrap";
import Card from "react-bootstrap/Card";
import Button from "react-bootstrap/Button";
import Row from "react-bootstrap/Row";
import {NavLink, useLocation, useHistory} from "react-router-dom";
import {LOGIN_ROUTE, REGISTRATION_ROUTE, SHOP_ROUTE} from "../utils/consts";
import {login, registration} from "../http/userAPI";
import {observer} from "mobx-react-lite";
import {Context} from "../index";

const Auth = observer(() => {
    const {user} = useContext(Context)
    const location = useLocation()
    const history = useHistory()
    const isLogin = location.pathname === LOGIN_ROUTE
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')

    const click = async () => {
        try {
            let data;
            if (isLogin) {
                data = await login(email, password);
            } else {
                data = await registration(email, password);
            }
            user.setUser(user)
            user.setIsAuth(true)
            history.push(SHOP_ROUTE)
        } catch (e) {
            alert(e.response.data.message)
        }

    }

    return (
        <Container
            className="d-flex justify-content-center align-items-center"
            style={{height: window.innerHeight - 54}}
        >
            <Card style={{width: 600}} className="p-5">
                <h2 className="m-auto">{isLogin ? 'Авторизация' : "Регистрация"}</h2>
                <Form className="d-flex flex-column">
                    <Form.Control
                        className="mt-3"
                        placeholder="Введите ваш email..."
                        value={email}
                        onChange={e => setEmail(e.target.value)}
                    />
                    <Form.Control
                        className="mt-3"
                        placeholder="Введите ваш пароль..."
                        value={password}
                        onChange={e => setPassword(e.target.value)}
                        type="password"
                    />
                    <Row className="d-flex justify-content-between mt-3 pl-3 pr-3">
                        {isLogin ?
                            <div>
                                Нет аккаунта? <NavLink to={REGISTRATION_ROUTE}>Зарегистрируйся!</NavLink>
                            </div>
                            :
                            <div>
                                Есть аккаунт? <NavLink to={LOGIN_ROUTE}>Войдите!</NavLink>
                            </div>
                        }
                        <Button
                            variant={"outline-success"}
                            onClick={click}
                        >
                            {isLogin ? 'Войти' : 'Регистрация'}
                        </Button>
                    </Row>

                </Form>
            </Card>
        </Container>
    );
});

export default Auth;


вот еще userApi если хотите посмотреть на полный принцип работы
import {$authHost, $host} from "./index";
import jwt_decode from "jwt-decode";

export const registration = async (email, password) => {
    const {data} = await $host.post('api/user/registration', {email, password, role: 'ADMIN'})
    localStorage.setItem('token', data.token)
    return jwt_decode(data.token)
}

export const login = async (email, password) => {
    const {data} = await $host.post('api/user/login', {email, password})
    localStorage.setItem('token', data.token)
    return jwt_decode(data.token,)
}

export const check = async () => {
    const {data} = await $authHost.get('api/user/auth' )
    localStorage.setItem('token', data.token)
    return jwt_decode(data.token)
}
Ответить с цитированием
  #6 (permalink)  
Старый 03.07.2025, 11:28
Аспирант
Отправить личное сообщение для riaron86 Посмотреть профиль Найти все сообщения от riaron86
 
Регистрация: 27.11.2021
Сообщений: 94

нужен код стейт менеджера от mobx-react-lite?
Ответить с цитированием
  #7 (permalink)  
Старый 03.07.2025, 11:38
Аспирант
Отправить личное сообщение для riaron86 Посмотреть профиль Найти все сообщения от riaron86
 
Регистрация: 27.11.2021
Сообщений: 94

вот UserStore.js
import {makeAutoObservable} from "mobx";

export default class UserStore {
    constructor() {
        this._isAuth = false
        this._user = {}
        makeAutoObservable(this)
    }

    setIsAuth(bool) {
        this._isAuth = bool
    }
    setUser(user) {
        this._user = user
    }

    get isAuth() {
        return this._isAuth
    }
    get user() {
        return this._user
    }
}

и индекс из userApi
import axios from "axios";

const $host = axios.create({
    baseURL: process.env.REACT_APP_API_URL
})

const $authHost = axios.create({
    baseURL: process.env.REACT_APP_API_URL
})

const authInterceptor = config => {
    config.headers.authorization = `Bearer ${localStorage.getItem('token')}`
    return config
}

$authHost.interceptors.request.use(authInterceptor)

export {
    $host,
    $authHost
}
Ответить с цитированием
  #8 (permalink)  
Старый 03.07.2025, 11:50
Аватар для ksa
ksa ksa вне форума
CacheVar
Отправить личное сообщение для ksa Посмотреть профиль Найти все сообщения от ksa
 
Регистрация: 19.08.2010
Сообщений: 14,276

Сообщение от riaron86
выдает ту же ошибку
Так судя по тексту ошибки, ты попадаешь на строку
Сообщение от riaron86
alert(e.response.data.message)
И там нет ключа data...

Защититься можно так
alert(e.response?.data?.message ?? 'Какая-то фигня получилась')
Ответить с цитированием
  #9 (permalink)  
Старый 03.07.2025, 12:36
Аспирант
Отправить личное сообщение для riaron86 Посмотреть профиль Найти все сообщения от riaron86
 
Регистрация: 27.11.2021
Сообщений: 94

без вызова функции check в basketController все работает четко, в чем может быть причина и как мне вытащить данные из токена не обращаясь к check?
Ответить с цитированием
  #10 (permalink)  
Старый 03.07.2025, 13:19
Аспирант
Отправить личное сообщение для riaron86 Посмотреть профиль Найти все сообщения от riaron86
 
Регистрация: 27.11.2021
Сообщений: 94

а так вставляя правильные данные о пользователе пользователь не логинится
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Смена background при нажатии JIeuTo Общие вопросы Javascript 5 14.09.2018 18:48
Проблема при изменение типа в Store на ajax Ambassador ExtJS 2 06.09.2018 23:59
Проблема с радио кнопками px379 Общие вопросы Javascript 8 29.07.2013 09:30
Проблема, в менюшке Большой джо Элементы интерфейса 0 12.07.2009 17:12
Проблема спама lliberty AJAX и COMET 1 12.03.2009 16:47