dor*_*ork 6 authentication reactjs redux-saga react-boilerplate
我正在开发一个带有登录页面和应用程序其余页面的应用程序(应登录查看).我正在使用 react-boilerplate.从这里example,我编辑了我的asyncInjectors.js文件redirectToLogin和redirectToDashboard方法:
//asyncInjectors.js
export function redirectToLogin(store) {
return (nextState, replaceState) => {
const isAuthenticated = store.getState().get('app').get('isAuthenticated');
if (!isAuthenticated) {
replaceState({
pathname: '/login',
state: {
nextPathname: nextState.location.pathname,
},
});
}
};
}
export function redirectToDashboard(store) {
return (nextState, replaceState) => {
const isAuthenticated = store.getState().get('app').get('isAuthenticated');
if (isAuthenticated) {
replaceState('/');
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,我只是设置redirectToLogin为onEnter页面和redirectToDashboard登录页面.
它工作正常但是当F5登录时页面刷新()时,登录页面会短暂呈现,然后呈现实际页面.登录页面只是调度一个authenticate动作componentWillMount,然后重定向componentDidUpdate:
//login.js
componentWillMount() {
this.props.dispatch(authenticate());
}
componentDidUpdate(prevProps, prevState) {
if (this.props.isAuthenticated) {
const nextPathname = prevProps.location.state ? prevProps.location.state.nextPathname : '/';
browserHistory.push(nextPathname);
}
}
Run Code Online (Sandbox Code Playgroud)
页面的容器也具有相同的componentWillMount代码.不确定是不是因为传奇,但这里是代码:
//sagas.js
export function* login({ user, password }) {
try {
const token = yield call(app.authenticate, {
strategy: 'local',
user,
password,
});
return token;
} catch (error) {
return onError(error);
}
}
// For page refresh after logging in
export function* authenticate() {
try {
const token = yield call(app.authenticate);
return token;
} catch (error) {
return onError(error);
}
}
export function* logout() {
try {
const response = yield call(app.logout);
return response;
} catch (error) {
return onError(error);
}
}
export function* loginFlow() {
while (true) {
const request = yield take(LOGIN_REQUEST);
const winner = yield race({
auth: call(login, request.data),
logout: take(LOGOUT_REQUEST),
});
if (winner.auth && winner.auth.accessToken) {
yield put(actions.setAuthState(true));
}
}
}
export function* logoutFlow() {
while (true) {
yield take(LOGOUT_REQUEST);
yield put(actions.setAuthState(false));
yield call(logout);
browserHistory.push('/login');
}
}
export function* authenticateFlow() {
while (true) {
yield take(AUTHENTICATE);
const response = yield call(authenticate);
if (response && response.accessToken) {
yield put(actions.setAuthState(true));
}
}
}
export default [
loginFlow,
logoutFlow,
authenticateFlow,
];
Run Code Online (Sandbox Code Playgroud)
如何摆脱闪烁的登录页面?
编辑:当我尝试gouroujo的答案时,我无法注销.
//asyncInjectors.js
import jwtDecode from 'jwt-decode';
export function redirectToLogin(store) {
return (nextState, replaceState, callback) => {
const token = localStorage.token;
if (token) {
const jwt = jwtDecode(token);
if (jwt.exp <= (new Date().getTime() / 1000)) {
store.dispatch(actions.setAuthState(false));
replaceState({
pathname: '/login',
state: {
nextPathname: nextState.location.pathname,
},
});
}
}
store.dispatch(actions.setAuthState(true));
callback();
};
}
Run Code Online (Sandbox Code Playgroud)
当我点击刷新时,login page没有显示,但现在我无法注销.
您有两种方法可以避免在初始渲染时闪烁登录页面:使您的身份验证功能同步或等待加载页面的答案。
1- 检查您的令牌是否存在且客户端有效(到期日期),以选择是否必须首先将用户重定向到登录或仪表板页面。当服务器返回答案时,您可以纠正最初的猜测,但绝大多数情况下您不需要这样做。
用户登陆->
要检查令牌客户端,您必须检查本地存储。例如:
class App extends Component {
requireAuth = (nextState, replace) => {
if (!localStorage.token) {
replace({
pathname: '/login',
state: { nextPathname: nextState.location.pathname }
})
}
}
render() {
return (
<Router history={browserHistory}>
<Route path="/login" component={LoginPage} />
<Route
path="/"
component={AppLayout}
onEnter={this.requireAuth}
> ... </Route>
)
}
}
Run Code Online (Sandbox Code Playgroud)
如果您使用过期日期相对较短的令牌,您还必须检查过期日期,从而对令牌进行解码。
try {
const jwt = JWTdecode(token);
if (moment().isBefore(moment.unix(jwt.exp))) {
return nextState;
} else {
replace({
pathname: '/login',
state: { nextPathname: nextState.location.pathname }
})
}
} catch (e) {
replace({
pathname: '/login',
state: { nextPathname: nextState.location.pathname }
})
}
Run Code Online (Sandbox Code Playgroud)
2- 在收到服务器的答复之前显示加载屏幕。添加一些不透明度的 CSS 过渡效果以避免“闪光”
| 归档时间: |
|
| 查看次数: |
1745 次 |
| 最近记录: |