
03.07.2025, 10:29
|
Аспирант
|
|
Регистрация: 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()
|
|

03.07.2025, 10:52
|
 |
CacheVar
|
|
Регистрация: 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])
});
})
}
|
|

03.07.2025, 11:14
|
Профессор
|
|
Регистрация: 04.12.2012
Сообщений: 3,826
|
|
ksa, сигнатура метода verify:
jwt.verify(token, secretOrPublicKey, [options, callback])
Там метод/функция генерирующий новый токен нафиг не нужен.
|
|

03.07.2025, 11:18
|
 |
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,276
|
|
Сообщение от Nexus
|
Там метод/функция генерирующий новый токен нафиг не нужен.
|
По его коду, он так ИД пользователя получает...
Но с таким синтаксисом присваивание сработает только после завершения всего метода create...
На это я и обратил его внимание. Не более того...
|
|

03.07.2025, 11:25
|
Аспирант
|
|
Регистрация: 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)
}
|
|

03.07.2025, 11:28
|
Аспирант
|
|
Регистрация: 27.11.2021
Сообщений: 94
|
|
нужен код стейт менеджера от mobx-react-lite?
|
|

03.07.2025, 11:38
|
Аспирант
|
|
Регистрация: 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
}
|
|

03.07.2025, 11:50
|
 |
CacheVar
|
|
Регистрация: 19.08.2010
Сообщений: 14,276
|
|
Сообщение от riaron86
|
выдает ту же ошибку
|
Так судя по тексту ошибки, ты попадаешь на строку
Сообщение от riaron86
|
alert(e.response.data.message)
|
И там нет ключа data...
Защититься можно так
alert(e.response?.data?.message ?? 'Какая-то фигня получилась')
|
|

03.07.2025, 12:36
|
Аспирант
|
|
Регистрация: 27.11.2021
Сообщений: 94
|
|
без вызова функции check в basketController все работает четко, в чем может быть причина и как мне вытащить данные из токена не обращаясь к check?
|
|

03.07.2025, 13:19
|
Аспирант
|
|
Регистрация: 27.11.2021
Сообщений: 94
|
|
а так вставляя правильные данные о пользователе пользователь не логинится
|
|
|
|