Files
GKNB_MSTM071/Backend_ppt/authn_z/middlewares.tex
T
2026-02-24 01:29:59 +01:00

206 lines
5.7 KiB
TeX

\section{Middleware}
\begin{frame}[shrink=15]{Mi az a middleware?}
\begin{block}{Definíció}
Függvény HTTP kérés-válasz között, hozzáfér \texttt{req}, \texttt{res}, \texttt{next}-hez.
\end{block}
\begin{itemize}
\item Láncolható
\item Kérés előfeldolgozás, válasz utófeldolgozás
\item Kérés megszakítható
\end{itemize}
\end{frame}
\begin{frame}[shrink=15]{Middleware működése}
\begin{center}
\begin{tikzpicture}[node distance=1.4cm, auto]
\node (browser) [rectangle, draw, text width=1.5cm, text centered] {Browser};
\node (mw1) [rectangle, draw, right of=browser, xshift=1cm, text width=2cm, text centered] {MW 1\\Logger};
\node (mw2) [rectangle, draw, right of=mw1, xshift=1.5cm, text width=2cm, text centered] {MW 2\\Auth};
\node (route) [rectangle, draw, right of=mw2, xshift=1.5cm, text width=1.5cm, text centered] {Route};
\draw[->, thick] (browser) -- node[above] {Req} (mw1);
\draw[->, thick] (mw1) -- node[above] {\tiny next()} (mw2);
\draw[->, thick] (mw2) -- node[above] {\tiny next()} (route);
\draw[->, thick, dashed] (route) -- node[below] {Res} (browser);
\end{tikzpicture}
\end{center}
\begin{alertblock}{Fontos}
\texttt{next()} nélkül kérés megáll!
\end{alertblock}
\end{frame}
\begin{frame}[shrink=15]{Middleware típusok}
\begin{enumerate}
\item \textbf{Application-level}: \texttt{app.use()}
\item \textbf{Router-level}: \texttt{router.use()}
\item \textbf{Error-handling}: \texttt{(err, req, res, next)}
\item \textbf{Built-in}: \texttt{express.json()}, \texttt{express.static()}
\item \textbf{Third-party}: \texttt{cors}, \texttt{helmet}, \texttt{morgan}
\end{enumerate}
\end{frame}
\begin{frame}[fragile,shrink=20]{Logger middleware}
\begin{verbatim}
const logger = (req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
next();
};
app.use(logger);
app.get('/', (req, res) => {
res.json({ msg: 'Hello' });
});
// Kimenet:
// [2026-02-24T10:30:15.000Z] GET /
\end{verbatim}
\end{frame}
\begin{frame}[fragile,shrink=20]{Request timing middleware}
\begin{verbatim}
const timer = (req, res, next) => {
req.startTime = Date.now();
res.on('finish', () => {
const duration = Date.now() - req.startTime;
console.log(`${req.method} ${req.url} - ${duration}ms`);
});
next();
};
app.use(timer);
// GET /api/users - 145ms
\end{verbatim}
\end{frame}
\begin{frame}[fragile,shrink=20]{Validation middleware}
\begin{verbatim}
const validateEmail = (req, res, next) => {
const { email } = req.body;
const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!email || !re.test(email)) {
return res.status(400).json({ error: 'Invalid email' });
}
next();
};
app.post('/register', validateEmail, (req, res) => {
res.json({ success: true });
});
\end{verbatim}
\end{frame}
\begin{frame}[fragile,shrink=20]{Auth middleware}
\begin{verbatim}
const auth = (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'Token required' });
}
try {
const decoded = jwt.verify(token, SECRET);
req.user = decoded;
next();
} catch (err) {
res.status(403).json({ error: 'Invalid token' });
}
};
app.get('/protected', auth, (req, res) => {
res.json({ user: req.user });
});
\end{verbatim}
\end{frame}
\begin{frame}[fragile,shrink=20]{Role-based middleware}
\begin{verbatim}
const requireRole = (role) => {
return (req, res, next) => {
if (req.user.role !== role) {
return res.status(403).json({ error: 'Forbidden' });
}
next();
};
};
app.delete('/user/:id', auth, requireRole('admin'), (req, res) => {
res.json({ deleted: true });
});
\end{verbatim}
\end{frame}
\begin{frame}[fragile,shrink=20]{Error handling middleware}
\begin{verbatim}
// Mindig utolsóként!
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(err.status || 500).json({
error: err.message || 'Internal Server Error'
});
});
// Használat
app.get('/error', (req, res, next) => {
const err = new Error('Something broke!');
err.status = 500;
next(err);
});
\end{verbatim}
\end{frame}
\begin{frame}[fragile,shrink=20]{CORS middleware}
\begin{verbatim}
const cors = require('cors');
// Minden origin engedélyezése
app.use(cors());
// Specifikus beállítás
app.use(cors({
origin: 'https://frontend.com',
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE']
}));
\end{verbatim}
\end{frame}
\begin{frame}[shrink=15]{Built-in middleware}
\begin{itemize}
\item \texttt{express.json()}: JSON body parsing
\item \texttt{express.urlencoded()}: URL-encoded body parsing
\item \texttt{express.static()}: Static fájlok kiszolgálása
\end{itemize}
\begin{exampleblock}{Használat}
\texttt{app.use(express.json());}\\
\texttt{app.use(express.static('public'));}
\end{exampleblock}
\end{frame}
\begin{frame}[shrink=15]{Third-party middleware}
\begin{description}
\item[helmet] HTTP security headers
\item[morgan] HTTP request logger
\item[compression] Response compression (gzip)
\item[cookie-parser] Cookie parsing
\item[express-session] Session kezelés
\item[passport] Authentication
\end{description}
\end{frame}
\begin{frame}[shrink=15]{Middleware best practices}
\begin{enumerate}
\item Mindig hívd meg \texttt{next()}-et (vagy küldjél választ)
\item Error middleware utolsóként
\item Sorrendiség számít!
\item Global middleware-ek előre (\texttt{cors}, \texttt{helmet})
\item Route-specifikus middleware-ek közvetlenül route-hoz
\item Async middleware-eknél használj try-catch-et
\end{enumerate}
\end{frame}