我有这种情况。
/company/<company-id>
。/login
-> /company/
。我很好地处理了这种情况,只需导航到/company/<whatever id is first in the prefetch>
即可。您可以假设我的预取工作正常,并且下面的代码段仅在companyState.success
为true时触发。如我所说,它正在工作。
我是通过
// pretty sure i can handle this with regex better to capture other cases
// but that's beside the point for the scope of this question
const urlId = +location.pathname.replace("/company/", "")
const checkCompany = !!companyState.data.find(d => d.id === urlId)
if(checkCompany){
company.set(urlId)
}
else{
navigate("/404")
}
如果company.set(<company:id>)
确实进行了更新,我将在其中使用钩子,它将预取视图所需的所有其他信息。而且,company
是一个自定义上下文挂钩,因此它在我的应用程序中无处不在。
是否有更好的方法来处理?手动检查路径名似乎很麻烦。
您可以假设我的gatsby_node.js
具有正确的定义以允许客户端路由。
这是我的路由定义:(这是我放在pages文件夹中的内容)
const DashboardPage = () => (
<ProtectedRoute>
<Router>
<Company path="/company/*" />
</Router>
</ProtectedRoute>
)
最后在components文件夹中,
const Company = ({location}) => (
<Router>
<Main path="/:companyId">
<Summary path="/" />
.... other dashboard routes
</Main>
</Router>
)
答案 0 :(得分:0)
您必须假定客户端代码始终可以由恶意行为者更改。最终,您必须在后端确保用户只能请求他应该看到的资源。
您对客户端的解决方案对我来说似乎不错。除了手动检查URL路径然后重定向之外,我没有其他方法。
通过登录,需要为您的用户分配一个加密安全的cookie或令牌(例如JSON Web令牌),以便您始终可以确定其身份。每当公司ID路由到您的前端时,您的前端都需要将用户身份发送到您的后端。只有在那里,您才能免受代码操作的伤害。您的后端需要检查用户是否可以查看此页面。
这样,即使有人操纵您的客户端代码并取消了重定向,黑客也会盯着一个无用的空白页。
摘要:
您在客户端的方法很好。发送公司数据之前,请确保后端检查用户的身份。
答案 1 :(得分:0)
因此,我不用手动处理路由,而是仅使用ReachRouter的导航来模拟history.push()
,以避免重新呈现整个页面。 (类似地,状态更改也具有跟踪历史的好处)。后端受到身份验证令牌的完全保护,因此无需担心。
我下面的策略将处理这些情况:
/company
(应用将预取>默认情况下获取第一家公司>导航至/company/{id}
/company/{id}
(应用将预提取>导航至/company/{id}
>由该路由触发的组件将检查id的有效性,否则导航至404)我创建的策略是
pages
文件夹中的所说组件,在我的情况下,/company
应该是pages > company.js
或pages > company > index.js
/company/{id}
,它是所述组件的子级,纯粹是客户端路由。gatsby-node.js
具有必要的createPages
定义,以允许对所有/company/*
进行客户端路由/company
,以便当用户键入/company/{id}
时拒绝重定向以捕获第二种情况如果我显示代码,最好不要使用自定义的内置挂钩。
useRequest
仅给出一个axios类,其中true
参数表明它是已验证的必需请求。
useApi
仅提供了一个方便的(异步等待)功能,该功能包括dispatch
的redux状态并调用api本身。我正在使用thunk,所以success
和error
是标准的。
const CompanyDefault = ({location}) => {
const [loading, toggle] = useState(true)
const request = useRequest(true)
const companyApi = useApi(request, getCompanies)
const companyState = useSelector(({company}) => company)
const redirectToCompany = async () => await navigate(clientRoutes.COMPANY(companyState.data[0].id))
const fetchCompanies = async () => {
await companyApi()
toggle(false)
}
useEffect(() => {
if(companyState.data.length === 0){
fetchCompanies()
}
}, [])
if(loading){
return <Loading />
}
else if(companyState.error || companyState.data.length === 0){
return <Error callApi={companyApi} />
}
else if(companyState.success && (location.pathname === "/company" || location.pathname === "/company/")){
redirectToCompany()
}
return (
<Router>
<Company path="company/:companyId/*" />
</Router>
)
}
export default CompanyDefault
因此,公司模块将只是
const Company = ({companyId}) => (
// you now have companyId!
// do magic here, and check if that company id is valid.
<Router>
<Main path="/">
<Summary path="/" />
.... other dashboard routes
</Main>
</Router>
)
希望这更干净。如果有更好的方法,请告诉我! :D