Route Guard trong nextJs

Route Guard trong nextJs

Dưới đây là bài viết mình tìm hiểu được về route guard trong nextjs

Nextjs route guard component
Path: /components/RouteGuard.jsx

Component route guard chứa các logic ủy quyền phía máy khách cho ứng dụng nextjs, nó bao bọc component hiện tại trong next.js app component

Ủy quyền phía máy khách được triển khai trong chức năng authCheck(), nó được thực thi khi tải ứng dụng lần đầu tiên và trên mỗi lần thay đổi route. Nếu bạn cố gắng truy cập một trang an toàn (ví dụ: trang chủ) mà bạn không đăng nhâp, nội dung trang sẽ không được thực hiện và bạn sẽ được chuyển hướng về trang '/login'. Tham số returnUrl truy vấn chuyển hướng được bao gồm trong các tham số tuy vấn chuyển hướng để trang login có thể chuyển hướng người dùng trở lại trang mà họ đã yêu cầu ban đầu sau khi bạn đăng nhập thành công.

Thuộc tính authorized được sử dụng để ngăn việc hiển thị ngắn gọn các trang an toàn trước khi chuyển hướng vì mình không thể tìm thấy cách rõ ràng để thay đổi route bằng sự kiện routeChangeStart của nextjs và sau đó chuyển hướng đến một trang mới

		import { useState, useEffect } from 'react';
        import { useRouter } from 'next/router';
        import { userService } from 'services';
        export { RouteGuard };

        function RouteGuard({ children }) {
            const router = useRouter();
            const [authorized, setAuthorized] = useState(false);

            useEffect(() => {
                // on initial load - run auth check 
                authCheck(router.asPath);

                // on route change start - hide page content by setting 
                authorized to false  
                const hideContent = () => setAuthorized(false);
                router.events.on('routeChangeStart', hideContent);

                // on route change complete - run auth check 
                router.events.on('routeChangeComplete', authCheck)

                // unsubscribe from events in useEffect return function
                return () => {
                    router.events.off('routeChangeStart', hideContent);
                    router.events.off('routeChangeComplete', authCheck);
                }

                // eslint-disable-next-line react-hooks/exhaustive-deps
            }, []);

            function authCheck(url) {
                // redirect to login page if accessing a private page and 
                not logged in 
                const publicPaths = ['/login'];
                const path = url.split('?')[0];
                if (!userService.userValue && !publicPaths.includes(path))
                {
                    setAuthorized(false);
                    router.push({
                        pathname: '/login',
                        query: { returnUrl: router.asPath }
                    });
                } else {
                    setAuthorized(true);
                }
            }

        return (authorized && children);
       }

Component trong nextjs
Path: /page/_app.js

Thành phần App này là thành phần gốc của ứng dụng Next.js mẫu và nó có chứa HTML bên ngoài, điều hướng chính và thành phần cho trang hiện tại.

Thành phần trang hiện tại <Component {...pageProps} /> được bao bọc trong component route guard (<RouteGuard>) được thực hiện ủy quyền phía máy khách để ngăn người dùng chưa được xác thực truy cập các trang an toàn

		import Head from 'next/head';
        import 'styles/globals.css';
        import { Nav, RouteGuard } from 'components';

        export default App;

        function App({ Component, pageProps }) {
            return (
                <>
                    <Head>
                        <title>Next.js 11 - Basic HTTP Authentication
                            Example</title>
                        <link href="//netdna.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" />
                    </Head>

                    <div className="app-container bg-light">
                        <Nav />
                        <div className="container pt-4 pb-4">
                            <RouteGuard>
                                <Component {...pageProps} />
                            </RouteGuard>
                        </div>
                    </div>
                </>
            );
        }