在今天的文章中,我将向您展示如何在用户通过身份验证后在您的 React 应用程序中设置自动重定向到安全/受限页面。
介绍
假设在您的应用程序中,您有一个页面需要先进行身份验证,然后用户才能访问它,例如仪表板。这意味着在允许用户访问仪表板之前,他必须先登录。
现在,如果出于某种原因(会话超时、cookie 过期等),用户退出应用程序,但需要重新访问仪表板上的同一页面怎么办?或者他可能会尝试通过单击发送给他的电子邮件中的链接来访问仪表板上的信息?您如何将此用户重定向回他在身份验证后尝试访问的链接?
这个问题会让你立刻明白,要求用户先登录才能访问受限页面是不够的。但是您还应该在用户通过身份验证后立即将其重定向到受限页面。
仍然感到困惑?让我解释得更好
所以我有这个页面 http://my-website.com/dashboard/update-profile
需要用户在被允许访问之前进行身份验证。每当未通过身份验证的用户尝试访问它时,他将被重定向到 http://my-website.com/login
现在的目标是保留此 URL http://my-website.com/dashboard/update-profile
,以便当用户通过身份验证成功时,他将被重定向回该 URL。
我将向您展示如何在您的 React 应用程序中实现这一点,如果您理解其中的逻辑,您可以在任何地方实现它!
使用查询参数
在这种方法中,我将检查用户是否未登录,然后检索他试图访问的 URL,将其存储在查询参数 next
中,然后将他重定向到登录页面。如果身份验证成功,我会将他重定向回 next
查询参数中的 URL。
将此代码放在安全/受限页面(需要身份验证的页面)
为此,我需要做的第一件事是检查用户是否未登录。
useEffect(() => { isAuthenticated().then(res => { //check if user is not logged in if(!res){ //---- } }}, []) //make the function run only once when the component mounts
现在我们需要创建一个新的 URL 对象,其中包含该用户将被重定向到的链接,以便进行身份验证。
在我的例子中,它将是 /login
页面,我用它创建一个新的 URL 对象的原因是我将在稍后通过添加查询参数来操纵链接。
useEffect(() => { isAuthenticated().then(res => { //check if user is not logged in if(!res){ //create a URL object with the Login Link const loginUrl = new URL('http://my-website.com/login'); } }}, []) //make the function run only once when the component mounts
在我们继续之前,我们需要确保用户正在尝试访问仪表板中的受限页面。我们可以通过检查当前 URL 是否包含 /dashboard
.
我将在方法内使用正则表达式 match
对当前 URL 执行此搜索。
useEffect(() => { isAuthenticated().then(res => { //check if user is not logged in if(!res){ //create a URL object with the Login Link const loginUrl = new URL('http://my-website.com/login'); //check if user is trying to access dashboard without logging in if(window.location.href.match(new RegExp('/dashboard', 'i'))){ //--- } } }}, []) //make the function run only once when the component mounts
现在我们需要将用户尝试访问的链接作为查询参数附加到我们之前创建的 URL 对象,然后将用户从该 URL 对象重定向到 完整的 URL 。
useEffect(() => { isAuthenticated().then(res => { //check if user is not logged in if(!res){ //create a URL object with the Login Link const loginUrl = new URL('http://my-website.com/login'); //check if user is trying to access dashboard without logging in if(window.location.href.match(new RegExp('/dashboard', 'i'))){ //Get the url he wanted to visit const next = window.location.href //append it to the URL object loginUrl.searchParams.append('next', next); } //redirect the user to the full URL from the URL Object window.location.href = loginUrl.href.toString() } }}, []) //make the function run only once when the component mounts
这是我们到目前为止所做的。
例如,当未通过身份验证的用户尝试访问仪表板中的任何页面时 http://my-website.com/dashboard/update-profile
,他将被重定向到 http://my-website.com/login?next=http://my-website.com/dashboard/update-profile
。
现在,这里有一些事情要记住。
浏览器将尝试对 next
查询参数中的值进行编码,因为它是一个 URL,在我们访问该值之前,我们需要对其进行解码。
在我这边,这是我的地址栏的样子
如果用户通过身份验证,我们就该处理重定向了。
处理重定向
现在在您的 登录页面上,我们将创建一个变量,该变量将存储默认链接,如果身份验证成功,用户将被重定向到。
我们还将导入 useLocation
from react-router-dom
以便我们能够读取当前 URL 并检查它是否包含搜索(查询)参数。
import {useLocation} from 'react-router-dom';export default function Login(){ //invoke the function const location = useLocation(); //default page to redirect user after login let redirect = 'http://my-website.com/dashboard/home'; //check if there's search param in the URL if(location.search){ //--- }}
如果您不想使用该 useLocation
模块读取当前 URL,您同样可以直接使用 JavaScript 访问当前 URL。
export default function Login(){ //default page to redirect user after login let redirect = 'http://my-website.com/dashboard/home'; //create a URL object using the current url const url = new URL(window.location.href) //check if url contains a search parameter if(url.search){ //--- }}
无论您选择使用哪种方法,接下来要做的就是读取搜索参数并检查它是否包含 next
.
如果它包含 next
,我们将解码该值并将 redirect
变量的值重新分配给该 URL。
您还可以执行搜索以检查解码值是否包含 /dashboard
.
export default function Login(){ //default page to redirect user after login let redirect = 'http://my-website.com/dashboard/home'; //create a URL object using the current url const url = new URL(window.location.href) //check if url contains a search parameter if(url.search){ //read the search parameters const search = new URLSearchParams(url.search) //check if next parameter is present if(search?.get('next')){ //decode it const next = decodeURIComponent(search.get('next')) //check if dashboard is present in the URL if(next.match(new RegExp('/dashboard', 'i'))){ redirect = next; } } } //after authentication, redirect users to the redirect variable //window.location.href = redirect;}
因此,在身份验证之后,您应该将用户重定向到 redirect
变量的值,即解码后的 URL!
在下面观看我的实现
小提示
如果你想让你的重定向更清晰,你可以将 URL 存储在浏览器中 sessionStorage
,当你验证它时,你可以继续并从会话存储中删除它,然后将用户重定向到该 URL。
感谢您阅读。
嘘!我愿意参加网络开发和技术写作方面的演出!
额外的
我构建了一个 JavaScript 库,它能够使用正则表达式、验证规则和表单输入属性来验证您的前端表单。