所以我将我的受保护路由包含在HOC中,首先通过查看是否有令牌来检查该人是否经过身份验证。如果他们有令牌,则将其发送到服务器以查看它是否有效。如果有效,则刷新(如果它<15分钟)。在此过程中,如果令牌有效,则PERMIT_RENDER
的状态设置为true,允许组件呈现(如果是);如果没有,它只是一个加载屏幕,直到服务器响应。希望在下面的代码中清楚这一点。
无论如何,使用我当前的设置,当您第一次登录时,它会带您到/home
这是一条受保护的路线。您可以单击.nav
中的链接以在其他受保护路由之间切换。首次登录时问题是permitRender
正常工作并显示加载,直到服务器响应并将您带到/home
。此时似乎permitRender
应该回到false
,这样当您点击指向受保护路由的链接时,它就不会加载,直到服务器响应并且用户刚刚获得加载屏幕直到那时。但是,permitRender
一旦true
保持这种状态,除非您刷新屏幕。此外,它会在收到服务器响应之前自动导航到其他受保护的路由。
基本上,在挂载或更新后将permitRender
设置回false
的正确方法是什么,这样每次有人导航到受保护路由时都会触发我的加载组件?
对我来说似乎很直观的一些事情(请注意,你不知道React和hwo在setState
,componentDidMount()
,componentDidUpdate()
中使用componentDidMount(...state)
等等。 :
this.setState(this.state.auth.permitRender = false);
结果为cannot read property 'auth' of null
。
// ./helpers/require_auth.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { authRequired, refreshToken } from '../actions/authentication';
import Loading from './loading';
// This HOC not only protects certain routes by checking for existence of a token,
// but if the token exists it make sure it is current
// if it is current, it will refresh the token
export default function(ComposedComponent) {
class AuthenticationRequired extends Component {
// Check if the user has a token when protected route component is about to mount
// Route them to / if they do not
componentWillMount() {
if (!sessionStorage.getItem('token')) {
this.props.authRequired();
} else {
this.props.refreshToken();
}
}
// If the component will be updated then also check if user is authorized
componentWillUpdate() {
if (!sessionStorage.getItem('token')) {
this.props.authRequired();
} else {
this.props.refreshToken();
}
}
// Render the component if passing these checks
render() {
if (this.props.permitRender) {
return <ComposedComponent {...this.props} />
} else if (!this.props.permitRender) {
return <Loading />
}
}
}
//
function mapStateToProps(state) {
return {
permitRender: state.auth.permitRender
};
}
// Conenct to the authRequired action
return connect(mapStateToProps, { authRequired, refreshToken })(AuthenticationRequired);
}
// ./actions/authentication
import axios from 'axios';
import { push } from 'react-router-redux';
import { ROOT_URL } from '../../config/config.json';
// Establish the different types
export const AUTH_USER = 'auth_user';
export const UNAUTH_USER = 'unauth_user';
export const PERMIT_RENDER = 'permit_render';
// Refresh the token based on the users activity
export function refreshToken() {
return function(dispatch) {
axios
.post(
`${ROOT_URL}/api/auth/refresh/`,
{ 'token': sessionStorage.getItem('token') },
{ headers: {
'Content-Type': 'application/json',
}
})
.then(response => {
sessionStorage.setItem('token', response.data.token);
dispatch({ type: AUTH_USER });
dispatch({ type: PERMIT_RENDER });
})
.catch(error => {
sessionStorage.clear();
dispatch({ type: UNAUTH_USER });
dispatch(push('/'));
dispatch(authError('This session has expired. Please login to continue browsing.'));
});
}
}
// ./reducers/authentication.js
import {
AUTH_USER,
UNAUTH_USER,
PERMIT_RENDER,
} from '../actions/authentication';
export default function(state = {}, action) {
switch(action.type) {
case AUTH_USER:
return { ...state, error: '', authenticated: true };
case UNAUTH_USER:
return { ...state, authenticated: false };
case PERMIT_RENDER:
return { ...state, permitRender: true };
default:
return state;
}
return state;
}
// ./reducers/index.js
import { combineReducers } from 'redux';
import { reducer as form } from 'redux-form';
import { routerReducer } from 'react-router-redux';
import authReducer from './authentication';
import helpReducer from './help';
const rootReducer = combineReducers({
form,
router: routerReducer,
auth: authReducer,
help: helpReducer
});
export default rootReducer;
答案 0 :(得分:0)
查看yuantonito在此分享的帖子:
In terms of a stateless front-end client, how secure is this JWT logic?
我想到我可以做到以下几点:
// ./require_auth.js
import { unpermitRender } from '..actions/'
....
componentWillUnmount() {
this.props.unpermitRender();
}
....
// ./actions/authentication.js
export function unpermitRender() {
return function(dispatch) {
dispatch({
type: PERMIT_RENDER,
payload: false
});
};
}
然后我修改了./actions/authentication.js
中正在使用的其他地方:
dispatch({ type: PERMIT_RENDER })
要:
dispatch({ type: PERMIT_RENDER, payload: true }) // or false
这意味着我必须将reducer修改为:
// ./reducers/authentication.js
...
case PERMIT_RENDER:
return { ...state, permitRender: action.payload };
...
现在我正在加载屏幕在受保护的路由之间导航,并且仅在收到服务器响应时才进行渲染。