(Verwenden von Redux für die Statusverwaltung)
Wenn der Benutzer versucht, auf eine URL zuzugreifen, werde ich zuerst prüfen, ob ein Zugriffstoken verfügbar ist. Wenn nicht, wird er zur Anmeldeseite umgeleitet. Sobald sich der Benutzer über die Anmeldeseite anmeldet, speichern wir diese sowohl in localstorage als auch in unserem Redux-Status. (localstorage oder Cookies. Wir halten dieses Thema vorerst aus dem Kontext).
da Redux-Status als aktualisiert und Privaterouten neu gerendert werden. Jetzt haben wir Zugriffstoken, sodass wir zur Startseite weiterleiten können.
Speichern Sie die dekodierten Berechtigungsnutzdaten auch im Redux-Status und übergeben Sie sie an den Reaktionskontext. (Wir müssen keinen Kontext verwenden, aber um auf die Autorisierung in einer unserer verschachtelten untergeordneten Komponenten zuzugreifen, ist der Zugriff über den Kontext einfach, anstatt jede untergeordnete Komponente mit Redux zu verbinden.)
Auf alle Routen, die keine speziellen Rollen benötigen, kann direkt nach der Anmeldung zugegriffen werden. Wenn eine Rolle wie admin benötigt wird (wir haben eine geschützte Route erstellt, die prüft, ob er die gewünschte Rolle hatte, wenn er nicht zu einer nicht autorisierten Komponente umleitet).
Ähnliches gilt für jede Ihrer Komponenten, wenn Sie die Schaltfläche oder etwas basierend auf der Rolle deaktivieren müssen.
einfach können Sie auf diese Weise tun
const authorization = useContext(AuthContext);
const [hasAdminRole] = checkAuth({authorization, roleType:"admin"});
const [hasLeadRole] = checkAuth({authorization, roleType:"lead"});
<Button disable={!hasAdminRole} />Admin can access</Button>
<Button disable={!hasLeadRole || !hasAdminRole} />admin or lead can access</Button>
Was ist, wenn der Benutzer versucht, ein Dummy-Token in localstorage einzufügen? Da wir über ein Zugriffstoken verfügen, werden wir zur Home-Komponente umleiten. Meine Home-Komponente führt einen Restaufruf durch, um Daten abzurufen. Da das JWT-Token ein Dummy war, gibt der Restaufruf einen nicht autorisierten Benutzer zurück. Also rufe ich die Abmeldung auf (wodurch localstorage gelöscht und erneut zur Anmeldeseite umgeleitet wird). Wenn die Homepage statische Daten enthält und keine API-Aufrufe tätigt (dann sollten Sie im Backend einen API-Aufruf zur Token-Überprüfung haben, damit Sie überprüfen können, ob das Token REAL ist, bevor Sie die Homepage laden).
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, Switch } from 'react-router-dom';
import history from './utils/history';
import Store from './statemanagement/store/configureStore';
import Privateroutes from './Privateroutes';
import Logout from './components/auth/Logout';
ReactDOM.render(
<Store>
<Router history={history}>
<Switch>
<Route path="/logout" exact component={Logout} />
<Route path="/" exact component={Privateroutes} />
<Route path="/:someParam" component={Privateroutes} />
</Switch>
</Router>
</Store>,
document.querySelector('#root')
);
History.js
import { createBrowserHistory as history } from 'history';
export default history({});
Privateroutes.js
import React, { Fragment, useContext } from 'react';
import { Route, Switch, Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import { AuthContext, checkAuth } from './checkAuth';
import App from './components/App';
import Home from './components/home';
import Admin from './components/admin';
import Login from './components/auth/Login';
import Unauthorized from './components/Unauthorized ';
import Notfound from './components/404';
const ProtectedRoute = ({ component: Component, roleType, ...rest })=> {
const authorization = useContext(AuthContext);
const [hasRequiredRole] = checkAuth({authorization, roleType});
return (
<Route
{...rest}
render={props => hasRequiredRole ?
<Component {...props} /> :
<Unauthorized {...props} /> }
/>)};
const Privateroutes = props => {
const { accessToken, authorization } = props.authData;
if (accessToken) {
return (
<Fragment>
<AuthContext.Provider value={authorization}>
<App>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/login" render={() => <Redirect to="/" />} />
<Route exact path="/home" component={Home} />
<ProtectedRoute
exact
path="/admin"
component={Admin}
roleType="admin"
/>
<Route path="/404" component={Notfound} />
<Route path="*" render={() => <Redirect to="/404" />} />
</Switch>
</App>
</AuthContext.Provider>
</Fragment>
);
} else {
return (
<Fragment>
<Route exact path="/login" component={Login} />
<Route exact path="*" render={() => <Redirect to="/login" />} />
</Fragment>
);
}
};
// my user reducer sample
// const accessToken = localStorage.getItem('token')
// ? JSON.parse(localStorage.getItem('token')).accessToken
// : false;
// const initialState = {
// accessToken: accessToken ? accessToken : null,
// authorization: accessToken
// ? jwtDecode(JSON.parse(localStorage.getItem('token')).accessToken)
// .authorization
// : null
// };
// export default function(state = initialState, action) {
// switch (action.type) {
// case actionTypes.FETCH_LOGIN_SUCCESS:
// let token = {
// accessToken: action.payload.token
// };
// localStorage.setItem('token', JSON.stringify(token))
// return {
// ...state,
// accessToken: action.payload.token,
// authorization: jwtDecode(action.payload.token).authorization
// };
// default:
// return state;
// }
// }
const mapStateToProps = state => {
const { authData } = state.user;
return {
authData: authData
};
};
export default connect(mapStateToProps)(Privateroutes);
checkAuth.js
import React from 'react';
export const AuthContext = React.createContext();
export const checkAuth = ({ authorization, roleType }) => {
let hasRequiredRole = false;
if (authorization.roles ) {
let roles = authorization.roles.map(item =>
item.toLowerCase()
);
hasRequiredRole = roles.includes(roleType);
}
return [hasRequiredRole];
};
DEKODIERTE JWT-TOKEN-PROBE
{
"authorization": {
"roles": [
"admin",
"operator"
]
},
"exp": 1591733170,
"user_id": 1,
"orig_iat": 1591646770,
"email": "hemanthvrm@stackoverflow",
"username": "hemanthvrm"
}