Az előző fejezetben felépítettünk egy webalkalmazást, ahová bejelentkezhetünk és megvédhetjük az útvonalakat a nem hitelesített felhasználóktól.
Mielőtt új funkciókat adnánk hozzá az alkalmazásunkhoz, frissítenünk kell a felhasználói felületünket, mert az jelenleg kissé ingerszegény. De emiatt nem kell aggódnunk, mivel ehhez már remek eszközeink vannak. Korábban telepítettük a Material-UI könyvtárat, így most először is létrehozunk egy MainLayout komponenst. Ez foglalja keretbe a webalkalmazásunk tartalmát.
>>> resources/js/components/MainLayout/MainLayout.js
import React from "react";
import {Container} from "@mui/material";
function MainLayout({children}) {
return (
<Container>
{children}
</Container>
)
}
export default MainLayout
Amint látjátok, az alkalmazás tartalma gyermekként kerül át az komponenshez. Ennek ellenére később átadhatunk weboldal- és oldalspecifikus paramétereket, például az oldal nevét, hogy milyen tartalmak jelenjenek meg a fejlécben (App Bar-ban) stb.
Most már használhatjuk ezt a komponenst a főoldal egységbe foglalásához:
>>> resources/js/components/Dashboard/Dashboard
import React from "react";
import user from "../../Models/user";
import {Grid, Typography} from "@mui/material";
import MainLayout from "../MainLayout/MainLayout";
function Dashboard() {
return (
<MainLayout>
<Grid container justifyContent={"center"}>
<Grid item>
<Typography variant={"h5"}>
Hello {user.name}, you're logged in!
</Typography>
</Grid>
</Grid>
</MainLayout>
)
}
export default Dashboard
Figyeljük meg, hogy nem kell használnunk a Container-t a Dashboard komponensben, mert a MainLayoutban már megtettük. A Dashboard komponensből adatokat is átadhatunk a MainLayoutnak, például az oldal címét:
{...}
<MainLayout title={"Dashboard"}>
{...}
Most már elérhetjük a title változót a wrapper komponensben. Vegyünk néhány változtatást a jobb megjelenés érdekében:
import React from "react";
import {
AppBar,
Paper,
Container,
Box,
CssBaseline,
Toolbar,
Typography
} from "@mui/material";
function MainLayout({children, title}) {
return (
<React.Fragment>
<CssBaseline/>
<AppBar position={"static"}>
<Toolbar>
<Typography
variant={"h6"}
component={"div"}
sx={{flexGrow: 1}}
>
{title} // Here is our passed data!
</Typography>
</Toolbar>
</AppBar>
<Container>
<Box
sx={{
marginTop: 8,
display: 'flex',
width: '100%',
height: '100%',
flexDirection: 'column',
alignItems: 'center',
}}
>
<Paper sx={{
width: '100%',
padding: 2
}}>
{children}
</Paper>
</Box>
</Container>
</React.Fragment>
)
}
export default MainLayout
Most már valamennyivel szebb felületünk van.
Érvénytelenítsük a sessiont
Session alapú hitelesítést használunk. Ellenkező esetben a Sanctum segítségével teljesen token alapú hitelesítést készíthetnénk. Azonban a jelenlegi megvalósításunkhoz, létrehozunk egy új metódust a LoginControllerben, úgynevezett logout-ot, amely érvényteleníti a hitelesített felhasználó aktuálisan használt munkamenetét (session-jét).
>>> app/Controllers/LoginController
/**
* @param Request $request
* @return JsonResponse
*/
public function logout(Request $request): JsonResponse
{
$request->session()->invalidate();
$request->session()->regenerateToken();
return response()->json('Successfully logged out');
}
Az api útvonalak fájljában néhány változtatást eszközöltünk a jobb megjelenés érdekében. Először is csoportosítottuk útvonalainkat, melyek hitelesítést igényelnek, majd ezt követően meghatároztuk a kijelentkezési útvonalat.
>>> routes/api.php
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\LoginController;
Route::post('login', [LoginController::class, 'authenticate']);
Route::group(['middleware' => 'auth:sanctum'], function (){
Route::get('/user', function (Request $request) {
return $request->user();
});
Route::post('/logout', [LoginController::class, 'logout']);
});
Kijelentkezés a kliens oldalon
Amikor kijelentkezünk az alkalmazásunkból, szeretnénk megbizonyosodni arról, hogy minden felhasználóhoz kapcsolódó adat (amit a kliens oldalon tárolunk) törlődik. A user.js-ben új metódust hozunk létre a takarításhoz.
>>> resources/js/Models/user.js
{...}
/**
* Remove all user's data from local storage
*/
destroy() {
localStorage.removeItem('userName')
localStorage.removeItem('userEmail')
localStorage.removeItem('userLoggedIn')
}
/**
*
* @param callback function
*/
logout(callback) {
this.destroy()
callback()
}
{...}
Létrehozunk egy új Kijelentkezési gomb komponenst, ami elvégzi a feladatot:
>>> resources/js/components/MainLayout/LogoutButton/LogoutButton
import React from "react";
import {Button, Box} from "@mui/material";
function LogoutButton() {
const logout = (e) => {
e.preventDefault()
//log out..
}
return (
<React.Fragment>
<Box component={"form"} onSubmit={logout}>
<Button color={'inherit'} type={"submit"}>
Logout
</Button>
</Box>
</React.Fragment>
)
}
export default LogoutButton
Ezt a gombot hozzáadhatjuk a Dashboard title-je után:
>>> resources/js/components/MainLayout/MainLayout
{...}
<Toolbar>
<Typography
variant={"h6"}
component={"div"}
sx={{flexGrow: 1}}
>
{title}
</Typography>
<LogoutButton/>
</Toolbar>
{...}
Ezt követően megjelenik a gomb. Most megcsinálhatjuk a kijelentkezés logikáját:
import React from "react";
import {Button, Box} from "@mui/material";
import user from "../../../Models/user";
import {withRouter} from "react-router-dom";
function LogoutButton({history}) {
const logout = (e) => {
e.preventDefault()
window.axios.post('/api/logout')
.then(() => {
//successful response
})
.catch(() => {
//handle if something went wrong
})
.then(() => {
//this code will be definitely executed
user.logout(afterUserDestroyed)
})
}
const afterUserDestroyed = () => {
history.push('/app/login')
}
return (
<React.Fragment>
<Box component={"form"} onSubmit={logout}>
<Button
type={"submit"}
color={'inherit'}
>
Logout
</Button>
</Box>
</React.Fragment>
)
}
export default withRouter(LogoutButton)
Az axios "második” then() promise metódusát használtuk, mert az mindig végrehajtásra kerül. Ez egy egyszerű megoldás, ha fel akarjuk készíteni az alkalmazásunkat a szerver oldali hibákra, vagy bármilyen egyéb felmerülő problémára. Így biztosak lehetünk abban, hogy a felhasználó kijelentkezik a kliens oldalon.
A projekt frissített Github könyvtárát itt megtaláljátok, ahol a működő kódhoz is hozzáfértek. Reméljük, hasznosnak tartottátok cikkünket! Hasonló szakmai írásokért olvassátok el további blogbejegyzéseinket!
A cikk eredeti változata elérhető itt. Fordította: Kádár Kyra