React Redux无法验证用户

时间:2019-04-03 05:09:59

标签: reactjs authentication redux react-redux

我有一个React-redux应用程序,我想实现用户登录/注册。对于登录/注册,我使用Django API。我想根据用户登录名创建一些公用和专用路由。

下面是我的代码:

LoginComponent.jsx

import React, { Component } from "react";
import RightPanel from "../AdBanner/RightPanel";
import Panel from "react-bootstrap/es/Panel";
import { connect } from "react-redux";
import * as actions from "../../store/actions/auth";

class Login extends Component {
  constructor(props) {
    super(props);

    this.state = {
      username: "",
      password: ""
    };
  }

  handleUsernameChange = e => {
    this.setState({ username: e.target.value });
  };

  handlePasswordChange = e => {
    this.setState({ password: e.target.value });
  };

  handleSubmit = e => {
    e.preventDefault();
    this.props.onAuth(
      this.state.username,
      this.state.password,
      "",
      "",
      "0",
      "",
      "0"
    );
     console.log(this.props.isAuthenticated);
     if (this.props.isAuthenticated) this.redirectToHome();
     else {
        this.setState({ errorMsg: "Bad credentials!" });
        setTimeout(() => {
          this.setState({ errorMsg: "" });
        }, 3000);
     }

  };

  redirectToHome = () => <Redirect to={{ pathname: "/" }} />;

  render() {
    let errorMessage = null;
    if (this.props.error) {
      errorMessage = <p>{this.props.error}</p>;
    }

    return (
      <section className="body_panel">
        <div className="container">
          <div className="row">
            <div className="col-md-7 padding-lef">
              <div className="section-title">
                <h3>MySite</h3>
                <h1>User Login</h1>
              </div>
              <div className="inner-content" id="login-panel">
                {errorMessage}
                <Panel>
                  <Panel.Body>
                    <div className="col-sm-12">
                      <label className="col-sm-4">Email-ID:</label>
                      <div className="col-sm-8">
                        <input
                          type="text"
                          className="form-control"
                          onChange={this.handleUsernameChange}
                        />
                      </div>
                    </div>
                    <div className="col-sm-12">
                      <label className="col-sm-4">Password:</label>
                      <div className="col-sm-8">
                        <input
                          type="password"
                          className="form-control"
                          onChange={this.handlePasswordChange}
                        />
                      </div>
                    </div>
                    <div
                      className="col-md-12 no-padding"
                      style={{ marginTop: "20px" }}
                    >
                      <div className="col-sm-4" />
                      <div className="col-sm-8">
                        <button
                          type="button"
                          className="btn"
                          onClick={this.handleSubmit}
                        >
                          Login
                        </button>
                      </div>
                    </div>
                  </Panel.Body>
                </Panel>
              </div>
            </div>
            <RightPanel />
          </div>
        </div>
      </section>
    );
  }
}

const mapStateToProps = state => {
  return {
    loading: state.loading,
    error: state.error
  };
};

const mapDispatchToProps = dispatch => {
  return {
    onAuth: (
      email,
      password,
      user_android_id,
      user_fcm_token,
      user_social_flag,
      user_name,
      user_fb_id
    ) =>
      dispatch(
        actions.authLogin(
          email,
          password,
          user_android_id,
          user_fcm_token,
          user_social_flag,
          user_name,
          user_fb_id
        )
      )
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(Login);

商店/动作/auth.jsx

import * as actionTypes from "./actionTypes";
import axios from "axios";

export const authStart = () => {
  return {
    type: actionTypes.AUTH_START
  };
};

export const authSuccess = (token, user) => {
  return {
    type: actionTypes.AUTH_SUCCESS,
    token: token,
    user: user
  };
};

export const authFail = error => {
  return {
    type: actionTypes.AUTH_FAIL,
    error: error
  };
};

export const logout = () => {
  localStorage.removeItem("user");
  localStorage.removeItem("token");
  localStorage.removeItem("expirationDate");
  return {
    type: actionTypes.AUTH_LOGOUT
  };
};

//method to check expiration date
export const checkAuthTimeout = expirationTime => {
  return dispatch => {
    setTimeout(() => {
      dispatch(logout);
    }, expirationTime * 1000);
  };
};

export const authLogin = (
  email,
  password,
  user_android_id,
  user_fcm_token,
  user_social_flag,
  user_name,
  user_fb_id
) => {
  return dispatch => {
    dispatch(authStart());
    axios
      .post("http://api.mydomain.in/user-login/", {
        email: email,
        password: password,
        user_android_id: user_android_id,
        user_fcm_token: user_fcm_token,
        user_social_flag: user_social_flag,
        user_name: user_name,
        user_fb_id: user_fb_id
      })
      .then(res => {
        // console.log(res.data);
        if (res.data.result === 1) {
          const token = res.data.key;
          const user = res.data.user_id;
          const expirationDate = new Date(new Date().getTime() + 3600 * 1000); //time duaryion of 1hour
          // logic to store user session
          // we need to store in something that persist
          // so we store in localstorage
          localStorage.setItem("token", token);
          localStorage.setItem("user", user);
          localStorage.setItem("expirationDate", expirationDate);
          dispatch(authSuccess(token, user));
          dispatch(checkAuthTimeout(3600));
        } else {
          // console.log("user fail");
          dispatch(authFail("User not registered"));
        }
      })
      .catch(err => {
        dispatch(authFail(err));
      });
  };
};
export const authSignup = (
  email,
  password1,
  password2,
  username,
  phone_no,
  user_android_id,
  user_fcm_token,
  user_social_flag,
  user_fb_id,
  user_android_app_version
) => {
  return dispatch => {
    dispatch(authStart());
    axios
      .post("http://api.mydomain.in/registration/", {
        email: email,
        password1: password1,
        password2: password2,
        name: username,
        phone_no: phone_no,
        user_android_id: user_android_id,
        user_fcm_token: user_fcm_token,
        user_social_flag: user_social_flag,
        user_fb_id: user_fb_id,
        user_android_app_version: user_android_app_version
      })
      .then(res => {
        const token = res.data.key;
        const user = res.data.user_id;
        const expirationDate = new Date(new Date().getTime() + 3600 * 1000); //time duration of 1hour
        // logic to store user session
        // we need to store in something that persist
        // so we store in localstorage
        localStorage.setItem("token", token);
        localStorage.setItem("user", user);
        localStorage.setItem("expirationDate", expirationDate);
        dispatch(authSuccess(token, user));
        dispatch(checkAuthTimeout(3600));
      })
      .catch(err => {
        dispatch(authFail(err));
      });
  };
};

export const authCheckState = () => {
  return dispatch => {
    const token = localStorage.getItem("token");
    const user = localStorage.getItem("user");
    if (token === undefined && user === undefined) {
      dispatch(logout());
    } else {
      const expirationDate = new Date(localStorage.getItem("expirationDate"));
      if (expirationDate <= new Date()) {
        dispatch(logout());
      } else {
        dispatch(authSuccess(token, user));
        dispatch(
          checkAuthTimeout(
            (expirationDate.getTime() - new Date().getTime()) / 1000
          )
        );
      }
    }
  };
};

App.jsx

import React, { Component } from "react";
import { Router, Route, Switch } from "react-router-dom";
import { Helmet } from "react-helmet";
import Header from "./components/Header_footer/Header";

import Footer from "./components/Header_footer/Footer";
import AdBannerTop from "./components/AdBanner/AdBannerTop";
import AdBannerLeft from "./components/AdBanner/AdBannerLeft";
import Login from "./components/Auth/Login";
import ProtectedPage from "./components/protected/ProtectedPage";
import ReactGA from "react-ga";
import * as actions from "./store/actions/auth";
import { connect } from "react-redux";
import { PrivateRoute } from "./components/PrivateRoute";
import createBrowserHistory from "history/createBrowserHistory";

const history = createBrowserHistory();
ReactGA.initialize("UA-*******-2");
history.listen((location, action) => {
  ReactGA.pageview(location.pathname + location.search);
});

class App extends Component {
  componentDidMount() {
    this.props.onTryAutoSignup();
    ReactGA.pageview(window.location.pathname + window.location.search);
  }
  componentDidUpdate = () =>
    ReactGA.pageview(window.location.pathname + window.location.search);

  render() {
    return (
      <Router history={history}>
        <React.Fragment>
          <Helmet>
            <title>My site</title>
            <meta name="description" content="my site description" />
          </Helmet>
          <Header {...this.props} />
          <AdBannerTop />
          <AdBannerLeft />
          <Switch>
            <PrivateRoute exact path="/protected-page/" component={ProtectedPage}
        />
            <Route exact path="/user-login/" component={Login} />
          </Switch>

          <Footer />
        </React.Fragment>
      </Router>
    );
  }
}

const mapStateToProps = state => {
  return {
    isAuthenticated: state.token !== null,
    user: state.user == null ? null : state.user
  };
};

const mapDispatchToProps = dispatch => {
  return {
    onTryAutoSignup: () => dispatch(actions.authCheckState())
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App);

index.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import { BrowserRouter } from "react-router-dom";
import { createStore, compose, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import { Provider } from "react-redux";
import reducer from "./store/reducers/auth";
require("dotenv").config();
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducer, composeEnhancers(applyMiddleware(thunk)));

const app = (
  <Provider store={store}>
    <App />
  </Provider>
);

ReactDOM.render(app, document.getElementById("root"));

serviceWorker.unregister();

我的问题:

  1. 要创建公用路由和专用路由(仅在用户登录时可访问)。如果用户单击任何私有路由,而不是重定向到登录页面而没有任何消息,则希望该用户收到类似“您需要登录才能访问此消息”的消息。相反,我的私人路线具有如下重定向:

    <Route {...rest} render={props => localStorage.getItem("user") ? ( <Component {...props} /> ) : ( <Redirect to={{ pathname: "/user-login", state: { from: props.location } }} /> ) } />

另外,成功登录后,用户应重定向到他来自的页面,而不是导航到主页。

请提出一个更好的方法。

谢谢。

1 个答案:

答案 0 :(得分:0)

您需要将redux-thunkredux集成。

https://github.com/reduxjs/redux-thunk

不进行重击,就无法处理authCheckState函数的条件。默认的redux分派将立即解决该问题。