当用户在浏览器选项卡中手动更改路线并按Enter键时,我遇到了问题。这会强制我的反应路由器导航到用户输入的状态。我想阻止这种情况,只允许通过我在网站上按下按钮实现的流程进行路由。
我的某些屏幕需要的数据仅在用户使用预期的流量浏览网站时才可用。如果用户通过手动更改URL中的路径直接尝试导航到特定路线,那么他可能会跳过所需的流程,因此应用程序将会中断。
其他情况,如果我想限制某些用户访问某些路由,但用户知道路径并在浏览器URL中手动输入该路径,那么他将会看到该屏幕,但不应该是。
答案 0 :(得分:2)
我要做的是使用上一页中的道具,如果该道具未定义(意味着用户未遵循适当的流程:) hehe),我只是将用户返回到登录页面或任何地方。
答案 1 :(得分:1)
您可以使用HOC创建路线保护。例如,您不希望未经授权的用户通过路由/profile
,那么您可以执行以下操作:
// requireAuthorized.js (HOC)
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {Redirect} from 'react-router-dom'
const connector = connect(
state => ({
isAuthorized: state.profile !== null // say, you keep user profile in redux
})
)
export default (WrappedComponent) => {
return (
connector(
class extends Component {
static propTypes = {
isAuthorized: PropTypes.bool.isRequired
}
render () {
const {isAuthorized, ...clearedProps} = this.props
if (isAuthorized) {
return <WrappedComponent {...clearedProps} />
} else {
return <Redirect to={{pathname: '/login'}} />
}
}
}
)
)
}
// ProfilePage.jsx
import React from 'react'
...
import requireAdmin from '../hocs/requireAdmin' // adjust path
class ProfilePage extends React.Component {
...
render () {
return (
<div>
...
</div>
)
}
}
export default requireAdmin(ProfilePage)
注意我ProfilePage.js
答案 2 :(得分:1)
这样的事情是合适的。您使用包装来处理身份验证/上下文道具的HOC路由。 注意:这涉及直接访问路线,而不是菜单项等。必须在菜单/ menuItem组件上以相同的方式对待它。
import requireAuth from "../components/login/requireAuth";
class Routes extends React.Component<RoutesProps, {}> {
render() {
return (
<div>
<Switch>
<Route exact={true} path="/" component={requireAuth(Persons, ["UC52_003"])} />
<Route path="/jobs" component={requireAuth(Jobs, ["UC52_006"])} />
</Switch>
</div>
)
}
}
export default function (ComposedComponent, privileges) {
interface AuthenticateProps {
isAuthenticated: boolean
userPrivileges: string[]
}
class Authenticate extends React.Component<AuthenticateProps, {}> {
constructor(props: AuthenticateProps) {
super(props)
}
render() {
return (
isAuthorized(this.props.isAuthenticated, privileges, this.props.userPrivileges) &&
<ComposedComponent {...this.props} /> || <div>User is not authorised to access this page.</div>
);
}
}
function mapStateToProps(state) {
return {
isAuthenticated: state.userContext ? state.userContext.isAuthenticated : false,
userPrivileges: state.userContext ? state.userContext.user ? state.userContext.user.rights : [] : []
};
}
return connect(mapStateToProps, null)(Authenticate);
}
答案 3 :(得分:0)
我建议使用this library作为最干净的解决方案(或至少对其进行个人类似的实现)。
然后您将创建身份验证检查HOC:
export const withAuth = connectedReduxRedirect({
redirectPath: '/login',
authenticatedSelector: state => state.user.isAuthenticated, // or whatever you use
authenticatingSelector: state => state.user.loading,
wrapperDisplayName: 'UserIsAuthenticated'
});
您可以轻松创建流HOC:
export const withFlow = (step) = connectedReduxRedirect({
redirectPath: '/initial-flow-step',
authenticatedSelector: state => state.flow[step] === true,
wrapperDisplayName: 'FlowComponent'
});
然后初始化您的组件
const AuthenticatedComponent = withAuth(Dashboard)
const SecondStepComponent = withFlow("first-step-finished")(SecondStep)
const ThirdStepComponent = withFlow("second-step-finished")(ThirdStep)
您可以通过组成HOC轻松地创建经过身份验证的流程步骤:
const AuthSecondStepComponent = withAuth(withFlow("first-step-finished")(SecondStep))
仅重要的一点是,在逐步执行流程时,请正确更新Redux状态。用户完成第一步后,您将设置
state.flow["first-step-finished"] = true // or however you manage your state
这样,当用户手动导航到特定页面时,他就不会具有该Redux状态,因为它处于内存中状态,并将被重定向到redirectPath
路由。