web-dev-qa-db-de.com

Reaktion - Wie gehe ich am besten mit dem authentifizierten/angemeldeten Status um?

Neu zu reagieren und an einer Anwendung mit Authentifizierung/Anmelden zu arbeiten. Derzeit funktioniert es, fühlt sich aber zusammen gehackt an. Momentan habe ich meinen isAuthenticated-Status in meinem routes.js wie folgt:

class Routes extends Component {

    constructor(props) {
        super(props);

        this.state = {
            isAuthenticated: false,
         }
     }

Auf meiner Anmeldeseite muss ich wissen, wann ein Benutzer authentifiziert wird, um ihn auf die Seite home umzuleiten. Welches ist das beste Entwurfsmuster, um den Zugriff und die Bearbeitung dieses isAuthenticated-Zustands zu ermöglichen? Wie ich es momentan eingerichtet habe, ist, dass ich eine Funktion habe, die den Status im routes.js festlegt und den Status als Requisite sendet:

 setAuthenticated = (isAuthenticated) => {
        this.setState({isAuthenticated});
    }

und unten im Router ...

<Route path="/" exact component={() =>
                            <div>
                                <Login
                                    isAuthenticated={this.state.isAuthenticated}
                                    setAuthenticated={this.setAuthenticated}
                            </div>
                        } />

Ja, ich verstehe, dass dies ein schlechtes Design ist, weil dies Requisitenwerte verändert, die unveränderlich sein sollen. Dies ist auch deshalb schlecht, wenn ich diesen Wert in meinem login.js ändere, was zu mehrfachem unnötigen Wiederherstellen führt. Soll ich isAuthenticated als eine Art globale Variable deklarieren? Ich verwende übrigens keine staatliche Verwaltung.

Edit: Ich setze isAuthenticated basierend auf einer Antwort von meinem Server, die die korrekte Kombination aus Login und Passwort bestätigt.

5
Vincent Nguyen

Wenn Ihr Seitenschutz auf einer Statusvariablen 'isAuthenticated' basiert, sollten Sie wahrscheinlich Deaktivieren der Reaktionstools in der Produktion. Andernfalls ist es möglich, die Seite zu überprüfen und das Flag manuell auf true zu setzen, wodurch die geschützte Seite einem nicht authentifizierten Benutzer angezeigt wird.

4
bje

Wenn Sie isAuthenticated nur in Ihrem App-Status verwenden, bedeutet dies, dass der Benutzer bei jeder Aktualisierung der Seite nicht authentifiziert wird. Stattdessen kann die Anmeldeseite ein Token in den Cookies oder im lokalen Speicher festlegen, um zu bestätigen, dass der Benutzer authentifiziert ist. Dann können Sie diesen Wert auf den anderen Seiten überprüfen. Sie benötigen wahrscheinlich auch ein Token, um Daten auf Ihrem Server abzurufen (indem Sie das Token im Header der Anforderungen übergeben). Dies ist auf jeden Fall eine Lösung, die Sie beachten sollten.

Hier sind einige der Methoden und speziellen Komponenten, die ich zur Authentifizierung verwende.

isAuthenticated ()

import Cookies from 'js-cookie'

export const getAccessToken = () => Cookies.get('access_token')
export const getRefreshToken = () => Cookies.get('refresh_token')
export const isAuthenticated = () => !!getAccessToken()

authentifizieren()

export const authenticate = async () => {
  if (getRefreshToken()) {
    try {
      const tokens = await refreshTokens() // call an API, returns tokens

      const expires = (tokens.expires_in || 60 * 60) * 1000
      const inOneHour = new Date(new Date().getTime() + expires)

      // you will have the exact same setters in your Login page/app too
      Cookies.set('access_token', tokens.access_token, { expires: inOneHour })
      Cookies.set('refresh_token', tokens.refresh_token)

      return true
    } catch (error) {
      redirectToLogin()
      return false
    }
  }

  redirectToLogin()
  return false
}

redirectToLogin ()

const redirectToLogin = () => {
  window.location.replace(
    `${getConfig().LOGIN_URL}?next=${window.location.href}`
  )
  // or history.Push('/login') if your Login page is inside the same app
}

AuthenticatedRoute

export const AuthenticatedRoute = ({
  component: Component,
  exact,
  path,
}) => (
  <Route
    exact={exact}
    path={path}
    render={props =>
      isAuthenticated() ? (
        <Component {...props} />
      ) : (
        <AuthenticateBeforeRender render={() => <Component {...props} />} />
      )
    }
  />
)

AuthenticateBeforeRender

class AuthenticateBeforeRender extends Component {
  state = {
    isAuthenticated: false,
  }

  componentDidMount() {
    authenticate().then(isAuthenticated => {
      this.setState({ isAuthenticated })
    })
  }

  render() {
    return this.state.isAuthenticated ? this.props.render() : null
  }
}
4
GG.

Wenn Sie eine Anwendung verwenden, bei der die Authentifizierung nur für eine Sitzung gilt, reicht das Speichern im Status aus. Beachten Sie jedoch, dass der Benutzer bei der Seitenaktualisierung den authentifizierten Status verliert. 

Hier ist ein Beispiel mit React Context, bei dem wir Kontext mit createContext erstellen und Consumer verwenden, um in der gesamten Anwendung darauf zuzugreifen.

const AuthenticationContext = React.createContext();
const { Provider, Consumer } = AuthenticationContext;

function Login(props) {
  return (
    <Consumer>
      {
        value=>
        <button onClick={value.login}>Login</button>
      }
    </Consumer>
  );
}

function Logout() {
  return (
    <Consumer>
      {
        value=>
        <button onClick={value.logout}>Logout</button>
      }
    </Consumer>
  );
}

function AnotherComponent() {
  return (
    <Consumer>
      {
        value=>{
          return value.isAuthenticated?
            <p>Logged in</p>:
            <p>Not Logged in</p>
        }
      }
    </Consumer>
  );
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.login = ()=> {
      this.setState({
        isAuthenticated: true
      });
    }
    this.logout = ()=> {
      this.setState({
        isAuthenticated: false
      });
    }
    this.state = {
      isAuthenticated: false,
      login: this.login,
      logout: this.logout
    }
  }
  
  render() {
    return (
      <Provider value={this.state}>
        <Login />
        <Logout />
        <AnotherComponent />
      </Provider>
    );
  }
}
ReactDOM.render(<App />, document.getElementById("root"));
<script crossorigin src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
<div id="root"></div> 

https://reactjs.org/docs/context.html#reactcreatecontext

sie können das Zugriffstoken im lokalen Speicher bei der Anmeldung festlegen und nach der Abmeldung des Benutzers löschen. Die authentifizierte Methode wird dann verwendet, um zu überprüfen, ob ein Token vorhanden ist und ob das Token gültig ist, während ein API-Aufruf ausgeführt wird

1
Waweru Mwaura