如何使用标头中的用户 JWT 令牌转发授权并将其与 cookie 中的 JWT 令牌进行比较以验证用户?
Posted
技术标签:
【中文标题】如何使用标头中的用户 JWT 令牌转发授权并将其与 cookie 中的 JWT 令牌进行比较以验证用户?【英文标题】:How do I forward authorization with the user JWT token in the header and compare it to the JWT token in the cookie to Auth user? 【发布时间】:2021-12-07 06:10:01 【问题描述】:我的登录用户有问题,当我刷新页面时,用户迷路了。这就是我分配 JWT 令牌的方式:
const signToken = id =>
return jwt.sign( id , 'my-ultra-secure-and-ultra-long-secret',
expiresIn: '14d',
);
;
这也是我使用此函数向 cookie 发送令牌的方式:
const createSendToken = (user, statusCode, res) =>
const token = signToken(user._id);
const cookieOptions =
expires: new Date(Date.now() + 14 * 1000 * 60 * 24),
httpOnly: true,
;
res.cookie('jwt', token, cookieOptions);
// Remove password from output
user.password = undefined;
res.status(statusCode).json(
status: 'success',
token,
data:
user,
,
);
;
这是我的登录控制器:
exports.login = catchAsync(async (req, res, next) =>
const email, password = req.body;
// 1) Check if email and password exist
if (!email || !password)
return next(new AppError('Please provide email and password!', 400));
// 2) Check if user exists && password is correct
const user = await User.findOne( email ).select('+password');
if (user && (await user.correctPassword(password, user.password)))
createSendToken(user, 200, res);
else
return next(new AppError('Incorrect email or password', 401));
);
这是我的 Protect 控制器(保护中间件):
exports.protect = catchAsync(async (req, res, next) =>
// 1) Getting token and check of it's there
let token;
if (
req.headers.authorization &&
req.headers.authorization.startsWith('Bearer')
)
token = req.headers.authorization.split(' ')[1];
if (!token)
return next(
new AppError('You are not logged in! Please log in to get access.', 401)
);
// 2) Verification token
const decoded = await promisify(jwt.verify)(
token,
'my-ultra-secure-and-ultra-long-secret'
);
// 3) Check if user still exists
const currentUser = await User.findById(decoded.id);
if (!currentUser)
return next(
new AppError(
'The user belonging to this token does no longer exist.',
401
)
);
// 4) Check if user changed password after the token was issued
if (currentUser.changedPasswordAfter(decoded.iat))
return next(
new AppError('User recently changed password! Please log in again.', 401)
);
// GRANT ACCESS TO PROTECTED ROUTE
req.user = currentUser;
res.locals.user = currentUser;
next();
);
这是我使用这个中间件的私有路由:
router.route('/:id').get(authController.isLoggedIn, postController.getPost);
问题是当我登录时我得到一个 cookie,但我无法访问受保护的路由(我得到一个错误令牌未定义)。当我刷新页面时,用户丢失了,但 cookie 仍在存储中。当我尝试通过邮递员访问保护路由并将授权承载添加到标题时.....(令牌)我可以访问它。
这是我的前端用户减速器:
export const userLoginReducer = (state = , action) =>
switch (action.type)
case USER_LOGIN_REQUEST:
return loading: true, isAuthenticated: false ;
case USER_LOGIN_SUCCESS:
return
loading: false,
isAuthenticated: true,
user: action.payload,
;
case USER_LOGIN_FAIL:
return loading: false, isAuthenticated: false, error: action.payload ;
case USER_LOGOUT:
return loading: false, isAuthenticated: false, user: null ;
default:
return state;
;
这是我的用户操作:
export const login = (email, password) => async dispatch =>
try
dispatch(
type: USER_LOGIN_REQUEST,
);
const config =
headers:
'Content-Type': 'application/json',
,
;
const data = await axios.post(
'/api/v1/users/login',
email, password ,
config
);
dispatch(
type: USER_LOGIN_SUCCESS,
payload: data,
);
catch (error)
dispatch(
type: USER_LOGIN_FAIL,
payload:
error.response && error.response.data.message
? error.response.data.message
: error.message,
);
;
这是我的登录屏幕:
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const redirect = location.search ? location.search.split('=')[1] : '/';
const dispatch = useDispatch();
const userLogin = useSelector(state => state.userLogin);
const loading, error, isAuthenticated = userLogin;
console.log(isAuthenticated);
useEffect(() =>
if (isAuthenticated)
history.push(redirect);
if (error)
console.log(error);
, [isAuthenticated, history, redirect, error]);
const submitHandler = e =>
e.preventDefault();
dispatch(login(email, password));
;
我在这里停留了大约 2 天,试图完成这个。请有人帮助我:)
【问题讨论】:
【参考方案1】:当您在 cookie 中设置 jwt 令牌时,您可以在发出请求时从那里读取它。您可以通过在您的 axios 配置对象中添加 withCredentials: true
来使用 axios 自动发送 cookie,例如:
axios(
withCredentials: true
)
在服务器端,您可以通过查看req.cookies
对象来获取 jwt cookie 值,例如:
let token;
if (req.cookies.jwt)
token = req.cookies.jwt;
【讨论】:
我不知道为什么会这样,但它可以“让令牌;如果(req.cookies.jwt)令牌= req.cookies.jwt;”现在当我有cookie时,我可以访问受保护的路线,当我从存储中删除 cookie 或注销时,我不能。那很好。现在我想知道如何让用户保持登录状态。登录时我在标题中显示用户名,这没关系,但是当我刷新页面时,我的用户消失了并得到错误 user.name is undefind 要了解 cookie 的工作原理,您可以查看expressjs.com/en/resources/middleware/cookie-parser.html。对于刷新页面问题,我认为有另一条路线来检查用户会话,比如让控制器验证 jwt 令牌并将用户信息作为名称返回,而在前端你可以在等待时处于加载状态用于用户会话检查。如果您使用的是反应路由器,这可以帮助您reactrouter.com/web/example/auth-workflow 当我登录并刷新您发送给我的链接上的页面(右侧输出)时,同一用户丢失了以上是关于如何使用标头中的用户 JWT 令牌转发授权并将其与 cookie 中的 JWT 令牌进行比较以验证用户?的主要内容,如果未能解决你的问题,请参考以下文章
如何模拟 JWT 令牌以将其与 Mockito 和 Spring Boot 一起使用