仅在刷新页面时令牌过期时注销?为啥?

Posted

技术标签:

【中文标题】仅在刷新页面时令牌过期时注销?为啥?【英文标题】:Logout when token expired only when page is refreshed? Why?仅在刷新页面时令牌过期时注销?为什么? 【发布时间】:2021-05-01 19:49:35 【问题描述】:

如果令牌过期并执行注销操作,我发现很难理解,最后一个操作仅在页面刷新时执行。虽然当令牌过期时抛出 401 代码,但它仍然使受保护的路由可见,并且只有刷新它才会注销并进入登录。它应该是这样还是不应该发生,我错过了什么?

这是前面的代码

import React,  useEffect  from 'react';
import  Route, Redirect  from 'react-router-dom';
import useDispatch from 'react-redux'
import  logoutUser  from '../redux/ActionCreators';
import  baseUrl  from '../shared/baseUrl'

export const PrivateRoute = ( component: Component, ...rest ) => 

    const dispatch = useDispatch()    
    
    useEffect(() => 
        // send jwt to API to see if it's valid
        let token = localStorage.getItem("token");
        if (token) 
            fetch(baseUrl + "protected", 
                method: "POST",
                headers: 
                    'Accept': 'application/json',
                    'Content-Type': 'application/json'
                ,
                body: JSON.stringify( token )
            )
                .then((res) => 
                    return res.json()
                )
                .then((json) => 
                    if (json.success) 
                    
                )
                .catch((err) => 
                    dispatch(logoutUser())
                )
         else 
            dispatch(logoutUser())
                
            
        , [])
        
        
    return (<Route ...rest render=props => (
        localStorage.getItem('token')
            ? <Component ...props />
            : <Redirect to= pathname: '/users/login', state:  from: props.location   />
    ) />)

和调用的api

protectedRouter.route('/')
    .options(cors.corsWithOptions, (req, res) =>  res.sendStatus(200) )
    .get(cors.cors, authenticate.verifyUser, authenticate.verifyAdmin, async (req, res, next) => 
        res.statusCode = 403
        res.end('Operation not supported')
    )
    .post(cors.corsWithOptions,  async (req, res, next) => 
        const token = req.body.token
        
        if (token) 
         try 
          return jwt.verify(token, process.env.secretKey);
          catch (err) 
          return null;
         
        
        return null;
) 

【问题讨论】:

钩子的工作量不大,但是当它第一次加载时,因为你有一个有效的令牌并且你正在使用 Promise,它最终会在这个组件已经渲染后获取 401。我也没有看到它与 redux store 绑定,那么它将如何刷新?注销用户操作是否会重新呈现页面? 你好。感谢您的回复...登录阶段正在使用 redux 进行,受保护的路由包含上面的所有代码以及我想要使其工作的所有代码,并且还通过查看示例来使其工作。当令牌过期时,它会抛出带有验证令牌的错误,因此会抛出 401 状态代码,并且具有受保护路由的页面将显示错误而不是内容,但页面仍然存在并且可以浏览它们。只有当我刷新页面时它才会注销并且受保护的路由不再可见或无法访问,所以我很困惑在实际应用程序中是否有必要这样做。 【参考方案1】:

可以有多种解决方法,最简单的就是重新渲染组件。只是一个例子。可能不是最干净的,但它会给你一个想法

const dispatch = useDispatch();
const  token, setToken  = useDispatch();

useEffect(() => 
        // send jwt to API to see if it's valid
        const token_from_storage = localStorage.getItem("token");
        setToken(token_from_storage);
        
        if (token_from_storage) 

        fetch(baseUrl + "protected", 
            method: "POST",
            headers: 
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            ,
            body: JSON.stringify( token )
        )
            .then((res) => 
                return res.json()
            )
            .then((json) => 
                if (json.success) 
                
            )
            .catch((err) => 
                setToken(undefined);
                dispatch(logoutUser())
            )
     else 
        setToken(undefined);
        dispatch(logoutUser())
    
, [])
            
    return (<Route ...rest render=props => (
                token
                    ? <Component ...props />
                    : <Redirect to= pathname: '/users/login', state:  from:                       
             props.location   />
            ) />)

当令牌失效或从存储中找不到时,它将重新渲染组件。 HTH。

【讨论】:

我将 const token, setToken = useDispatch() 更改为 const [ token, setToken ] = useState();因为它不是一个功能,它不允许我使应用程序工作,但不幸的是它根本不允许我去受保护的路线.. 它不允许我去受保护的页面,我被登录了但是当试图一遍又一遍地进入它就像一个刷新页面时:/

以上是关于仅在刷新页面时令牌过期时注销?为啥?的主要内容,如果未能解决你的问题,请参考以下文章

当 jwt 刷新令牌未过期时,React Native 应用程序注销

为啥我登录后刷新页面时 Laravel 会注销?

令牌输入仅在我刷新页面后才有效

过期后使用刷新令牌获取访问令牌(JWT)

在刷新重定向页面时丢失访问令牌

为啥 keycloak 在页面刷新时未经授权?