reactjs – 在React Router上,如何保持登录状态甚至刷新页面?

我正在使用React和React Router与Redux建立网站。许多路线(页面)需要登录。如果用户未登录,我可以重定向到登录:
function requireAuth(nextState,replace) {
    let loggedIn = store.getState().AppReducer.UserReducer.loggedIn;

    if(!loggedIn) {
        replace({
            pathname: '/login',state: {
                nextpathname: nextState.location.pathname
            }
        });
    }
}

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={Graph} onEnter={requireAuth}>
                    ... some other route requires logged in ...
                </Route>
            </Route>
        </Router>
    </Provider>,document.getElementById('entry')
);

如果用户没有登录,请查看代码,我使用onEnter挂钩重定向到’/ login’路由。用于检查用户登录的数据在商店中,并且在用户登录后将更新。

它工作得很好,但问题是当我刷新页面时,存储将被重置并且用户没有登录状态。

我知道这是因为Redux存储只是内存存储,所以refesh页面会丢失所有数据。

检查服务器会话每次刷新都可以工作,但这可能是太多的请求,所以这看起来不错。

将登录的状态数据保存到localStorage可能有效,但在这种情况下,我应该检查每个AJAX调用是否因为会话过期或不存在而拒绝该请求,这看起来也是个坏主意。

有没有办法更清楚地解决这个问题?我的网站将会使用很多人,所以我希望尽可能减少XHR呼叫。

任何建议将非常感谢。

另一种方法是使用每条路线所需的 JSON Web Tokens (JWT),以及 localStorage来检查JWT。

TL; DR

>在前端,您有一个登录和注册路径,可以查询您的
根据服务器上的身份验证,JWT的服务器。一旦
通过适当的JWT,然后你将状态的属性设置为
真正。您可以使用允许用户设置此选项的注销路线
陈述为假。
>包含路由的index.js可以检查本地存储
在渲染之前,从而消除了丢失状态的问题
刷新但保持一定的安全性。
>呈现在您的应用程序中需要身份验证的所有路由
通过组合组件,并根据需要进行保护
在标头中使用JWT进行服务器API的授权。

设置它需要一点时间,但它会使您的应用程序“合理”安全。

要解决您的问题:

检查index.js文件中路由之前的本地存储,如下所示,如果需要,将状态更新为已验证状态。

该应用程序通过JWT保护API以保护安全性,这将解决您的刷新问题,并维护与服务器和数据的安全链接。

因此在路线中你会有这样的东西:

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>,.getElementById('entry'));

RequiredAuth是组合组件,而Graph和IsAuthenticated(可以是任意数量的适当命名的组件)需要state.authenticated为true。

组件,在这种情况下,如果state.authenticated为true,则呈现Graph和IsAuthenticated。否则默认返回根路由。

然后你可以像这样构建一个Composed Component,通过它来渲染所有的路径。在渲染之前,它将检查您持有的状态,无论用户是否经过身份验证(布尔值)。

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的动作,并通过动作创建者设置要通过身份验证的状态 – > redux商店。此示例makes use of axios运行异步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!'));
      });
  };
}

你还需要设置你的商店(在这种情况下是Redux)和行动创建者。

“真正的”安全性来自后端。为此,您可以使用localStorage将JWT保留在前端,并将其在标头中传递给任何具有敏感/受保护信息的API调用。

在服务器API上为用户创建和解析JWT是另一个步骤。 I have found passport to be effective.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如果组件之中有复用的代码,需要重新创建一个父类,父类中存储公共代码,返回子类,同时把公用属性...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例如我们的 setState 函数式同步执行的,我们的事件处理直接绑定在了 dom 元素上,这些都跟 re...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom 转为真实 dom 进行挂载。其实函数是组件和类组件也是在这个基础上包裹了一层,一个是调...
react 本身提供了克隆组件的方法,但是平时开发中可能很少使用,可能是不了解。我公司的项目就没有使用,但是在很多三方库中都有使用。本小节我们来学习下如果使用该...
mobx 是一个简单可扩展的状态管理库,中文官网链接。小编在接触 react 就一直使用 mobx 库,上手简单不复杂。
我们在平常的开发中不可避免的会有很多列表渲染逻辑,在 pc 端可以使用分页进行渲染数限制,在移动端可以使用下拉加载更多。但是对于大量的列表渲染,特别像有实时数据...
本小节开始前,我们先答复下一个同学的问题。上一小节发布后,有小伙伴后台来信问到:‘小编你只讲了类组件中怎么使用 ref,那在函数式组件中怎么使用呢?’。确实我们...
上一小节我们了解了固定高度的滚动列表实现,因为是固定高度所以容器总高度和每个元素的 size、offset 很容易得到,这种场景也适合我们常见的大部分场景,例如...
上一小节我们处理了 setState 的批量更新机制,但是我们有两个遗漏点,一个是源码中的 setState 可以传入函数,同时 setState 可以传入第二...
我们知道 react 进行页面渲染或者刷新的时候,会从根节点到子节点全部执行一遍,即使子组件中没有状态的改变,也会执行。这就造成了性能不必要的浪费。之前我们了解...
在平时工作中的某些场景下,你可能想在整个组件树中传递数据,但却不想手动地通过 props 属性在每一层传递属性,contextAPI 应用而生。
楼主最近入职新单位了,恰好新单位使用的技术栈是 react,因为之前一直进行的是 vue2/vue3 和小程序开发,对于这些技术栈实现机制也有一些了解,最少面试...
我们上一节了了解了函数式组件和类组件的处理方式,本质就是处理基于 babel 处理后的 type 类型,最后还是要处理虚拟 dom。本小节我们学习下组件的更新机...
前面几节我们学习了解了 react 的渲染机制和生命周期,本节我们正式进入基本面试必考的核心地带 -- diff 算法,了解如何优化和复用 dom 操作的,还有...
我们在之前已经学习过 react 生命周期,但是在 16 版本中 will 类的生命周期进行了废除,虽然依然可以用,但是需要加上 UNSAFE 开头,表示是不安...
上一小节我们学习了 react 中类组件的优化方式,对于 hooks 为主流的函数式编程,react 也提供了优化方式 memo 方法,本小节我们来了解下它的用...
开源不易,感谢你的支持,❤ star me if you like concent ^_^
hel-micro,模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 ,欢迎关注与了解
本文主题围绕concent的setup和react的五把钩子来展开,既然提到了setup就离不开composition api这个关键词,准确的说setup是由...
ReactsetState的执行是异步还是同步官方文档是这么说的setState()doesnotalwaysimmediatelyupdatethecomponent.Itmaybatchordefertheupdateuntillater.Thismakesreadingthis.staterightaftercallingsetState()apotentialpitfall.Instead,usecom