(Utilisation de Redux pour la gestion de l'état)
Si l'utilisateur essaie d'accéder à une URL, je vais d'abord vérifier si le jeton d'accès est disponible, sinon rediriger vers la page de connexion.Une fois que l'utilisateur se connecte à l'aide de la page de connexion, nous le stockons dans le stockage local ainsi que dans notre état redux. (stockage local ou cookies .. nous gardons ce sujet hors de son contexte pour l'instant).
depuis l'état de redux comme mis à jour et les routes privées seront rendues. maintenant nous avons un jeton d'accès donc nous allons rediriger vers la page d'accueil.
Stockez également les données de charge utile d'autorisation décodées dans l'état redux et transmettez-les au contexte de réaction. (Nous n'avons pas besoin d'utiliser le contexte, mais pour accéder à l'autorisation dans l'un de nos composants enfants imbriqués, il est facile d'accéder à partir du contexte au lieu de connecter chaque composant enfant à redux).
Toutes les routes qui n'ont pas besoin de rôles spéciaux peuvent être accédées directement après la connexion .. Si elle a besoin d'un rôle comme admin (nous avons fait une route protégée qui vérifie s'il avait le rôle souhaité sinon redirige vers un composant non autorisé)
de même dans l'un de vos composants si vous devez désactiver le bouton ou quelque chose en fonction du rôle.
tu peux simplement faire de cette manière
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>
Alors que faire si l'utilisateur essaie d'insérer un jeton factice dans localstorage. Comme nous avons un jeton d'accès, nous redirigerons vers le composant d'accueil. Mon composant domestique effectuera un appel au repos pour récupérer des données, puisque le jeton jwt était factice, l'appel au repos retournera un utilisateur non autorisé. Donc, j'appelle la déconnexion (ce qui effacera le stockage local et redirigera à nouveau vers la page de connexion). Si la page d'accueil contient des données statiques et ne fait aucun appel d'API (alors vous devriez avoir un appel API de vérification de jeton dans le backend afin de pouvoir vérifier si le jeton est RÉEL avant de charger la page d'accueil)
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];
};
ÉCHANTILLON DE JWT DÉCODÉ
{
"authorization": {
"roles": [
"admin",
"operator"
]
},
"exp": 1591733170,
"user_id": 1,
"orig_iat": 1591646770,
"email": "hemanthvrm@stackoverflow",
"username": "hemanthvrm"
}