简体   繁体   English

为什么我在 React 应用程序中丢失了登录信息?

[英]Why am I losing my login in my React App?

I have an reactjs app that uses a django backend to deal with authentication.我有一个 reactjs 应用程序,它使用 django 后端来处理身份验证。

Here are the pertinent parts of my App.tsx Typescript code for my react app.这是我的 React 应用程序的 App.tsx Typescript 代码的相关部分。

import React, {useState, useEffect} from 'react';
import { BrowserRouter as Router, Route, Link, RouteComponentProps, Redirect } from 'react-router-dom';
import {AuthContext, useAuth} from "./context/auth";
import './App.css';
import PrivateRoute from "./PrivateRoute";
import logoImg from "./img/logo.svg";
import { Card, Logo, Form, Input, Button } from "./components/AuthForm";
import axios from 'axios';
import Cookies from 'js-cookie';


// The "Home" Page.
function Index() {
    const [appUser, setAppUser] = useState({pk:-1, username: '', email: '', first_name: '', last_name:''});
    const {authTokens} = useAuth();
    useEffect(()=> {
        if (authTokens) {
            const url = 'http://localhost:8000/rest-auth/user/';
            const withCredentials = true;
            const method = 'get';

            // the token is what we got from the backend when we logged in.
            const headers = {
                "Authorization": "Token " + authTokens['key'] + " "
            };
            axios.request({method, url, withCredentials, headers}).then(response => {
                console.log('Login() response is ', response);
                setAppUser((appUser) => ({...appUser, ...response.data}));
            })
            //    .catch(error => { setAppUser(null); setLoggedIn(false); })
        }
    }, [authTokens]);
    return authTokens ? (
        <h2>Home you are logged in. {appUser.first_name || 'No first name'} email is {appUser.email}</h2>
    ) : (
        <Router>
            <div>
                <h2>Home you not logged in.</h2>
                <nav>
                    <ul>
                        <li> <Link to="/login">Login</Link> </li>
                        <li> <Link to="/signup">Sign Up</Link> </li>
                    </ul>
                </nav>

                <Route path="/login" component={Login} />
                <Route path="/signup" component={Signup} />
            </div>
        </Router>
    );
}

function Login (props: RouteComponentProps<TParams>) {
  const [userName, setUserName] = useState("");
  const [password, setPassword] = useState("");
  const {authTokens, setAuthTokens} = useAuth();
  const [isError, setIsError] = useState(false);
  const referer = props.location.state ? props.location.state.referer : '/';
  const [appUser, setAppUser] = useState({pk:-1, username: '', email: '', first_name: '', last_name:''});
  const [isLoggedIn, setLoggedIn] = useState(false);

  useEffect(()=> {
      // axios.get('http://localhost:8000/api/v1/rest-auth/user/', {headers: { 'Authorization': `Token ${token}`}})
        if (!!authTokens) {
            const url = 'http://localhost:8000/rest-auth/user/';
            const withCredentials = true;
            const method = 'get';
            const headers = {
                "Authorization": "Token " + authTokens['key'] + " "
            };
            axios.request({method, url, withCredentials, headers}).then(response => {
                console.log('Login() /rest-auth/user response is ', response);
                // setAppUser({...appUser, ...response.data});
                setAppUser((appUser) => ({...appUser, ...response.data}));
                setLoggedIn(true);
            })
            //    .catch(error => { setAppUser(null); setLoggedIn(false); })
        }
  }, [authTokens]);

  function postLogin() {
        const url = 'http://localhost:8000/rest-auth/login/';
        const withCredentials = true;
        const method = 'post';
        const data = {"username": userName, "password": password};
        // BIG WARNING!!!
        // password is being passed unencrypted and in the clear.
        axios.request({url, withCredentials, data, method}).then(
            result => {
                // console.log('Login.postLogin.else result is :', result);
                if (result.status === 200) {
                    setAuthTokens(result.data);
                } else {
                    setIsError(true);
                }
            });// .catch(e => { console.log('Login.postLogin.catch e is :', e); setIsError(true); });
  } // end postLogin

  if (authTokens) {
    console.log('Login page authTokens is ', authTokens);
    console.log('Login page appUser is ', appUser);

    // UPDATE
    // SET sessionStorage cookie
    window.sessionStorage.setItem('key', authTokens['key']);

    return <Redirect to={referer}/>;
  } else {
    console.log('Login page authTokens is ', authTokens);
    console.log('Login page appUser is ', appUser);
  }

  return (
      <Card>
        <Logo src={logoImg} />
        <Form>
          <Input
              type="username"
              placeholder="username"
              value={userName}
              onChange={(e: { target: { value: React.SetStateAction<string>; }; }) => { setUserName(e.target.value); }}
          />
          <Input
              type="password"
              value={password}
              onChange={(e: { target: { value: React.SetStateAction<string>; }; }) => { setPassword(e.target.value); }}
              placeholder="password" />
          <Button onClick={postLogin}>Sign In</Button>
        </Form>
        <Link to="/signup">Don't have an account?</Link>
      </Card>
  );
}

const App: React.FunctionComponent = () => {
    const [authTokens, setAuthTokens] = useState(undefined);  //type: AuthTokens | undefined (see auth.js)
    // <AuthContext.Provider value={false}>
    return (
      <AuthContext.Provider value={{ authTokens, setAuthTokens }}>
        <Router>
          <div>
            <nav>
              <ul>
                <li> <Link to="/">Home</Link> </li>
                <li> <Link to="/products/1">First Product</Link> </li>
                <li> <Link to="/products/2">Second Product</Link> </li>
                <li> <Link to="/admin">Admin Page</Link> </li>
              </ul>
            </nav>

            <Route path="/" exact component={Index} />
            <Route path="/products/:id" component={Product} />
            <Route path="/login" component={Login} />
            <Route path="/signup" component={Signup} />
            <PrivateRoute path="/admin" component={Admin} />
            <Route path="/confirm-email/:id" component={ConfirmEmail} />
          </div>
        </Router>
      </AuthContext.Provider>
  );
};

export default App;

Now if I start my backend server and start my app with np start I can navigate in a browser to http://localhost:3000 and I see:现在,如果我启动我的后端服务器并使用np start启动我的应用程序,我可以在浏览器中导航到http://localhost:3000并且我看到:

在此处输入图片说明

and I can login if I click the "Login" link.如果我单击“登录”链接,我就可以登录。 Here is a screen shot of me logged in:这是我登录的屏幕截图:

在此处输入图片说明

I do notice that the browser location still reports http://localhost:3000/login while the "Home Page" is being displayed.我确实注意到在显示“主页”时浏览器位置仍然报告http://localhost:3000/login But we can see that a Sheldon Plankton has logged in. Now if I click on the links I have: Home, Product 1, Product 2 and Admin everything is fine.但是我们可以看到 Sheldon Plankton 已经登录。现在如果我点击我拥有的链接:Home、Product 1、Product 2 和 Admin,一切都很好。 But if I type in a URL into the browser like http://localhost:3000/ I lose my login and I see:但是,如果我在浏览器中输入一个 URL,例如http://localhost:3000/,我会丢失登录信息,然后看到:

在此处输入图片说明

Which shows that Sheldon Plankton is no longer logged in.这表明 Sheldon Plankton 不再登录。

What I am doing wrong?我做错了什么?

That's because you are storing login credentials in session's memory.那是因为您将登录凭据存储在会话的内存中。 When you change the URL on your own or refresh the page, the application's router (eg React Router) is not the routing the website.当您自己更改 URL 或刷新页面时,应用程序的路由器(例如 React Router)不是网站的路由。 It is the browser's native navigation system that loads it.加载它的是浏览器的本机导航系统。 As a result, all the memory that existed previously in the session is reset.因此,会话中先前存在的所有内存都将被重置。 It is loading a new page instead of navigating within the same page (do not let the URL change to fool you that it is actually a new page -- that's how HTML5 browser history works).它正在加载一个新页面,而不是在同一页面中导航(不要让 URL 更改以欺骗您它实际上是一个新页面——这就是 HTML5 浏览器历史记录的工作原理)。

You need to persist the state between sessions.您需要在会话之间保持状态。 You can do it using cookies, sessionStorage , or localStorage .您可以使用 cookie、 sessionStoragelocalStorage Do not forget that if you use session storage, your user's information will be deleted if you close the browser.不要忘记,如果您使用会话存储,如果您关闭浏览器,您的用户信息将被删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么我无法使用反应路由器路由我的应用程序? - Why am I not able to route my app using react router? 为什么我无法在我的基本React应用中使用Promise? - Why am I not able to use promise in my basic react app? Meteor:为什么我通过将function(){}切换到()=&gt; {}来丢失我的数据上下文? - Meteor: Why am I losing my data context by switching function() { } to () => { }? 为什么我用.innerText丢失了最后一个空字符? - Why am I losing my last empty character with .innerText? 我正在尝试通过 express 为我的 React 应用程序提供服务,为什么我会收到 404? - I'm trying to serve my react app from express, why am I getting a 404? 当我只更改状态而不使用任何 CSS 时,为什么我的 React 应用程序菜单会打开? - Why does my React app menu open when I am only changing the state and am not using any CSS? 为什么在尝试使用javascript动态添加html时,我的html字符串中的字符丢失了? - Why am I losing my characters from my html string when trying to add html dynamically using javascript 我无法在我的反应应用程序中设置间隔 - I am not able to set interval in my react app 我没有在我的 React-app 中获得列表项 - I am not getting the list item in my React-app 我正在尝试向我的 React 应用程序添加路由器 - I am trying to add a router to my react app
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM