我用React
,Redux
和React Router
创建了一个简单的Auth0
应用,用于处理用户身份验证。
我正在尝试创建此基本行为来控制访问:
/public
Auth0
认证,我想处理access_token
并将用户发送到/
,它是Home
组件一切都“几乎”按照应有的方式进行。我遇到的问题是render()
中的App.jsx
函数正在执行lock.on('authenticated')
侦听器之前,甚至有机会处理Auth0
返回的令牌。结果,令牌永远不会被存储,并且用户似乎总是未经身份验证。如果我将用户发送到/login
,则一切正常,因为在呈现Login
组件之前我没有检查用户是否已通过身份验证。
我认为我处理受保护路线的方式需要改变。关于如何处理受保护路线的任何建议?
我在这里提供您需要的代码。如果您想查看整个应用程序,请转到https://github.com/imsam67/react-redux-react-router-auth0-lock
以下是App.jsx
:
class App extends Component {
render() {
const isAuthed = isAuthenticated();
return (
<div>
<Switch>
<Route exact path="/" render={ props => isAuthed ? <Home {...props} /> : <Redirect to="/public" /> } />
<Route exact path="/login">
<Login />
</Route>
<Route path="/public">
<Public />
</Route>
</Switch>
</div>
);
}
}
这是我处理AuthWrapper
的Auth0
组件:
class AuthWrapper extends Component {
constructor(props) {
super(props);
this.onAuthenticated = this.onAuthenticated.bind(this);
this.lock = new Auth0Lock('my_auth0_client_id', 'my_domain.auth0.com', {
auth: {
audience: 'https://my_backend_api_url',
redirectUrl: 'http://localhost:3000/',
responseType: 'token id_token',
sso: false
}
});
this.onAuthenticated();
}
onAuthenticated() {
debugger; // After successful login, I hit this debugger
this.lock.on('authenticated', (authResult) => {
debugger; // But I never hit this debugger
let expiresAt = JSON.stringify((authResult.expiresIn * 1000) + new Date().getTime());
sessionStorage.setItem('access_token', authResult.accessToken);
sessionStorage.setItem('id_token', authResult.idToken);
sessionStorage.setItem('expires_at', expiresAt);
});
}
render() {
return(
<AuthContext.Provider value={{ lock: this.lock }}>
{this.props.children}
</AuthContext.Provider>
);
}
}
[这里是index.js
,如果您需要查看它:
import App from './components/App';
import AuthWrapper from './components/auth/AuthWrapper';
// Store
import appStore from './store/app-store';
const store = appStore();
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<AuthWrapper>
<App />
</AuthWrapper>
</BrowserRouter>
</Provider>,
document.getElementById('root')
);
这里是我为完成这项工作所做的更改。
Auth0 Lock
中的index.js
初始化为全局onAuthenticated()
侦听器移至LoginCallback.jsx
组件,这是成功登录后将用户发送到的组件。我相信将onAuthenticated()
从App.jsx
移至LoginCallback.jsx
的影响最大,因为LoginCallback.jsx
中的侦听器在App.jsx
之前执行。this.props.history.push('/');
将用户发送到Home
组件有关完整代码,请参见https://github.com/imsam67/react-redux-react-router-auth0-lock处的存储库>
请记住,客户端根本没有任何保护。如果您担心路由到没有身份验证的组件,只需确保没有暴露任何数据(假设没有令牌就无法获取任何数据),并在路由器检查身份验证或显示错误后将它们重定向到那里(如果它们登陆)。
请记住,客户端根本没有任何保护。如果您关心的是路由到没有身份验证的组件,只需确保没有数据泄露,即使路由器检查了身份验证后,如果数据降落到那里也将重定向。我认为@Sam正确。路由可能不会像预期的那样对更改它的异步调用做出响应,或者行为可能很奇怪。我从来没有尝试过这种动态路由,但是总是有条件地渲染内容组件。更好的方法可能是发送呼叫,然后在随后的块中重定向到路由器知道要处理的URL。只是不确定路由器是否可以很好地处理。捕获组件,以在加载时检查auth,如果未经授权,则重定向回登录。抱歉,我在这里没有太大帮助,但是条件路由似乎似乎是一种反模式,但是我想如果我们知道路由器在更改后如何呈现其数据或实际上是否能够执行数据(路由自己),它就可以工作。他们将网址加为书签,然后尝试返回404,对吗?也许像未经授权的401显示和重定向或登录链接可能更好?
动态路由需要在<Switch>
范围之外定义。这是一个示例,假设您的函数isAuthenticated()是一种状态(Redux或Wathever)