另一种方法是使用每条路由所需的JSON Web Tokens (JWT)个,使用localStorage个来判断JWT.
TL;DR
在前端,您有一条登录和注册路由,可以查询您的
索引.包含路由的js可以判断本地存储
将呈现应用程序中需要身份验证的所有路由
设置这个需要一点时间,但它会使你的应用程序"合理"安全.
To solve your problem:
Check the local storage before the routes in your 100 file as shown below, updating the state to authenticated if required.
该应用程序维护了API的安全性,因为该API由JWT保护,JWT将解决您的刷新问题,并维护到服务器和数据的安全链接.
因此,在路由中,你会有这样的东西:
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, compose } from 'redux';
import { Router, Route, browserHistory, IndexRoute } from 'react-router';
import reduxThunk from 'redux-thunk';
import { AUTHENTICATE_THE_USER } from './actions/types';
import RequireAuth from './components/auth/require_auth';
import reducers from './reducers';
/* ...import necessary components */
const createStoreWithMiddleware = compose(applyMiddleware(reduxThunk))(createStore);
const store = createStoreWithMiddleware(reducers);
/* ... */
// Check for token and update application state if required
const token = localStorage.getItem('token');
if (token) {
store.dispatch({ type: AUTHENTICATE_THE_USER });
}
/* ... */
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<Route path="/" component={App}>
<IndexRoute component={Index} />
<Route path="login" component={Login} />
<Route path="register" component={Register} />
<Route path="dashboard" component={RequireAuth(Graph)} />
<Route path="isauthenticated" component={RequireAuth(IsAuthenticated)} />
... some other route requires logged in ...
</Route>
</Router>
</Provider>
, document.getElementById('entry'));
RequiredAuth
是合成组件,而Graph
和IsAuthenticated
(可以是任意数量的适当命名组件)要求state.authenticated
为真.
如果state.authenticated
为真,则渲染组件(在本例中为Graph
和IsAuthenticated
).否则默认返回根路由.
然后,您可以构建一个这样的组合组件,通过它可以呈现所有路由.在呈现之前,它将判断您持有的用户是否经过身份验证(布尔值)的状态是否为真.
require_auth.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
export default function (ComposedComponent) {
// If user not authenticated render out to root
class Authentication extends Component {
static contextTypes = {
router: React.PropTypes.object
};
componentWillMount() {
if (!this.props.authenticated) {
this.context.router.push('/');
}
}
componentWillUpdate(nextProps) {
if (!nextProps.authenticated) {
this.context.router.push('/');
}
}
render() {
return <ComposedComponent {...this.props} />;
}
}
function mapStateToProps(state) {
return { authenticated: state.authenticated };
}
return connect(mapStateToProps)(Authentication);
}
在注册/登录端,您可以创建一个存储JWT的操作,并通过操作创建者将状态设置为已验证->;reduxstore .下面的示例演示如何运行异步HTTP请求-响应周期.
export function signinUser({ email, password }) {
// Note using the npm package 'redux-thunk'
// giving direct access to the dispatch method
return function (dispatch) {
// Submit email and password to server
axios.post(`${API_URL}/signin`, { email, password })
.then(response => {
// If request is good update state - user is authenticated
dispatch({ type: AUTHENTICATE_THE_USER });
// - Save the JWT in localStorage
localStorage.setItem('token', response.data.token);
// - redirect to the route '/isauthenticated'
browserHistory.push('/isauthenticated');
})
.catch(() => {
// If request is bad show an error to the user
dispatch(authenticationError('Incorrect email or password!'));
});
};
}
当然,你还需要建立你的store (本例中是Redux)和action creator.
真正的安全来自后端.要做到这一点,您可以使用localStorage将JWT保留在前端,并将其在头中传递给任何具有敏感/受保护信息的API调用.
在服务器API上为用户创建和解析JWT是另一个步骤.I have found passport to be effective.