我正在努力查明代码的问题所在。基本上,我已经建立了一个hooks.js文件,该文件检查并获取当前用户的详细信息(如果用户已通过身份验证),否则返回null。这个钩子应该是一个辅助功能,然后可以控制对页面的访问(即,尝试访问登录/注册页面的经过身份验证的用户将被重定向到仪表板,反之亦然)。
但是,它目前仅部分起作用。例如,如果我登录然后尝试访问登录/注册页面,它将自动将我重定向到仪表板页面。但是,如果我注销并尝试访问仪表板,则可以访问它,并且它不会将我重定向到登录页面。有人知道我在做什么错吗?我试图通过遵循代码流(在各个地方进行控制台日志记录)来调试它,甚至在hooks.js中,似乎应该已经执行了Router.push(redirectTo)代码。但它似乎没有做到。感谢您的任何帮助(以及下面的代码片段)!
hooks.js
import { useEffect } from 'react';
import Router from 'next/router';
import useSWR from 'swr';
const fetcher = (url) =>
fetch(url)
.then((r) => r.json())
.then((data) => {
if (data?.user) {
return { user: data?.user };
} else {
return null;
}
});
export function useUser({ redirectTo, redirectIfFound } = {}) {
const { data, error } = useSWR('api/users/profile', fetcher);
const user = data?.user;
const finished = Boolean(data);
const hasUser = Boolean(user);
useEffect(() => {
if (!redirectTo || !finished) return;
if (
// If redirectTo is set, redirect if the user was not found.
(Boolean(redirectTo) && !redirectIfFound && !hasUser) ||
// If redirectIfFound is also set, redirect if the user was found
(redirectIfFound && hasUser)
) {
Router.push(redirectTo);
}
}, [redirectTo, redirectIfFound, finished, hasUser]);
return error ? null : user;
}
dashboard.js
import React from 'react';
import PrivateRouteLayout from '../components/privateRouteLayouts';
import { useUser } from '../lib/hooks';
function Dashboard() {
useUser({ redirectTo: '/signin', redirectIfFound: false });
return (
<PrivateRouteLayout title='Dashboard'>
<div>
<h1>Welcome !</h1>
</div>
</PrivateRouteLayout>
);
}
export default Dashboard;
signinform.js
import React, { useState, useEffect } from 'react';
import Link from 'next/link';
import Router from 'next/router';
import { useUser } from '../lib/hooks';
import validateSigninInput from '../lib/validation/login';
function SigninForm() {
useUser({ redirectTo: '/dashboard', redirectIfFound: true });
const [userDetails, setUserDetails] = useState({
email: '',
password: '',
});
const [error, setError] = useState({
email: '',
password: '',
});
function handleChange(event) {
setError({
email: '',
password: '',
});
setUserDetails({
...userDetails,
[event.target.name]: event.target.value,
});
}
async function handleSubmit(event) {
event.preventDefault();
const body = userDetails;
try {
const res = await fetch('/api/users/signin', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
if (res.status === 200) {
Router.push('/dashboard');
} else if (res.status === 400) {
res.json().then((errMessage) => {
setError(errMessage);
});
}
} catch (error) {
console.error(error);
}
}
return (
<div className='valign-wrapper row auth-form-container'>
<div className='row'>
<div className='col s8 offset-s2'>
<Link href='/'>
<a>{'< Back to home page'}</a>
</Link>
</div>
<div className='input-field col s8 offset-s2'>
<label htmlFor='email'>Email</label>
<input
type='email'
onChange={handleChange}
name='email'
value={userDetails.email}
/>
<p className='error-message'> {error.email} </p>
</div>
<div className='input-field col s8 offset-s2'>
<label htmlFor='password'>Password</label>
<input
type='password'
onChange={handleChange}
name='password'
value={userDetails.password}
/>
<p className='error-message'>{error.password}</p>
</div>
<div className='col s8 offset-s2'>
<button
className='btn waves-effect waves-light submit-button'
onClick={handleSubmit}
>
Login
</button>
</div>
<div className='col s8 offset-s2 mt-10'>
<Link href='/register'>
<a>Don't have an account yet? Create one here</a>
</Link>
</div>
</div>
</div>
);
}
export default SigninForm;
答案 0 :(得分:0)
为此,您将必须从服务器端和客户端进行检查,以检查用户是否通过了受保护的路由的身份验证。将authInitialProps
用于受保护的页面。
dashboard.js
import React from 'react';
import PrivateRouteLayout from '../components/privateRouteLayouts';
import { useUser } from '../lib/hooks';
import { authInitialProps } from './auth';
function Dashboard() {
useUser({ redirectTo: '/signin', redirectIfFound: false });
return (
<PrivateRouteLayout title='Dashboard'>
<div>
<h1>Welcome !</h1>
</div>
</PrivateRouteLayout>
);
}
Dasboard.getInitialProps = authInitialProps(true);
export default Dashboard;
auth.js
const WINDOW_USER_SCRIPT_VAR = '__USER__';
// Server side function
export const getServerSideToken = (req) => {
const { signedCookies = {} } = req;
if (!signedCookies) {
return {};
} else if (!signedCookies.cookie) {
return {};
}
return { user: signedCookies.cookie };
};
export const getClientSideToken = () => {
if (typeof window !== 'undefined') {
const user = window[WINDOW_USER_SCRIPT_VAR] || {};
return { user };
}
return { user: {} };
};
/**
* Check for authenticated users
* @param {Boolean} isProtectedRoute
*/
export const authInitialProps = (isProtectedRoute) => ({ req, res }) => {
const auth = req ? getServerSideToken(req) : getClientSideToken();
const currentPath = req ? req.url : window.location.pathname;
const user = auth.user;
const isAnonymous = !user || user.type !== 'authenticated';
if (isProtectedRoute && isAnonymous && currentPath !== '/login') {
return redirectUser(res, `/login?redirect=${currentPath}`, currentPath);
}
return { auth };
};