背景:在快速后端上,我正在使用快速会话来分配用户会话。在React前端,我具有适当的功能来防止用户输入受保护的路由。不过,有一个麻烦的极端情况:如果经过身份验证的用户在应用程序中保留足够长的时间以使其cookie过期,那么他们将可以自由地访问所有经过身份验证的路由,称为“幽灵”(也就是没有cookie)和不正确的状态:this.state.isAuthenticated = true
(是,从技术上来说,它们的状态是“经过身份验证的”,因为它们从未注销或重新安装了该组件,从而阻止了我获取后端并执行检查,因此这就是为什么我将它们称为“鬼”)
为什么?嗯,每次安装我的App组件时,请确保检查用户状态。如果他们通过了身份验证阶段,那么我的后端将为他们提供会话,并且我将身份验证状态设置为true。因为我的应用程序组件永远不会重新安装,所以当用户遍历我的应用程序时,他们将能够以“幽灵”身份访问未经授权的路由。
Caveat:如果它们偶然在任何时候刷新或按注销按钮,则我的组件将重新安装,并删除其访问权限,因为它们不是合法用户。
我希望我已经做好了我的处境。我的问题是:如果Cookie过期,我该如何删除用户?
Edit:我在Protectedroute.js中有一个可行的解决方案,但是除非用户离开页面,否则checkAuth()的调用次数是无限的。 我想避免Redux,因为我一周前才开始使用React
ProtectedRoute.js
function ProtectedRoute({component: Component}, {...rest}) {
return(
<userContext.Consumer>
{({isAuthenticated, checkAuth}) => {
checkAuth()
return <Route {...rest} render = {(props) => isAuthenticated ? (<Component {...props}/>) : (<Redirect to ='/login' />)} />
}}
</userContext.Consumer>
)
}
App.js
class App extends Component {
constructor(props, context) {
super(props, context)
this.state = {
isAuthenticated: false,
isLoading: true
}
this.handleLoggedIn = this.handleLoggedIn.bind(this)
this.handleLoggedOut = this.handleLoggedOut.bind(this)
this.isAuthenticated = this.isAuthenticated.bind(this)
}
componentDidMount() {
//Get and set currently logged in user
//console.log('--componentDidMount--')
this.isAuthenticated()
}
isAuthenticated() {
const url = 'http://localhost:9000/api/auth'
fetch(url, {
method: 'GET',
credentials: 'include',
headers: {
'Content-Type' : 'application/json'
}
})
.then((response) => response.text())
.then((data) => {
//console.log(data)
if (data === 'true') {
console.log('--isAuthenticated--')
this.setState({
isAuthenticated: true,
isLoading: false
})
} else {
this.setState({
isAuthenticated: false,
isLoading: false
})
}
})
.catch((err) => {
console.log('Error', err)
})
}
handleLoggedIn() {
console.log('--handleLoggedIn--')
this.setState({
isAuthenticated: true
})
}
handleLoggedOut() {
this.setState({
isAuthenticated: false
})
}
render() {
const value = {
loggedIn: this.handleLoggedIn,
loggedOut: this.handleLoggedOut,
isAuthenticated: this.state.isAuthenticated,
checkAuth: this.isAuthenticated
}
if (this.state.isLoading) {
return(<div>LOADING</div>)
} else {
return (
<Router>
<userContext.Provider value = {value}>
<div>
<userContext.Consumer>
{(value) => (<Navigation isAuthenticated = {this.state.isAuthenticated} />)}
</userContext.Consumer>
</div>
<Switch>
<Route path = '/signup'>
<Signup />
</Route>
<Route path = '/login'>
<Login handleLoggedIn={this.handleLoggedIn}/>
</Route>
<Route path = '/feed'>
<Feed />
</Route>
<Protectedroute path = '/create-post' component={CreatePost} />
</Switch>
</userContext.Provider>
</Router>
)
}
}
}
您可以创建一个fetchWrapper,它将调用所有提取API到您的后端。每当您检测到从前端接收的cookie过期时,请发送401响应代码。在fetchWrapper中侦听401,并在遇到401时重新加载页面以登录路由。您的问题可能有多种解决方案,这就是其中之一。
很好地使用setTimeout
是检查n
时间间隔内cookie过期时间的方法。
[如果您不想使用setInterval
的另一种方法是,您可能想开发一种方法,以便检查每个安全请求的cookie,然后检查该请求状态代码是否返回了401
您的服务器,则可能会显示模式显示your session is expired, click here to login...