首頁  >  文章  >  web前端  >  使用臉部身份驗證建立安全的員工儀表板:綜合 Next.js 教程

使用臉部身份驗證建立安全的員工儀表板:綜合 Next.js 教程

WBOY
WBOY原創
2024-07-18 18:16:41620瀏覽

您準備好徹底改變您的職場管理了嗎?在這個綜合教程中,我們將深入研究如何創建一個利用臉部身份驗證的最先進的員工儀表板。我們將使用 Web 開發中一些最熱門的工具:Next.js、FACEIO 和 Shadcn UI。在本指南結束時,您將擁有一個時尚、安全的儀表板,讓您的員工感覺到他們生活在未來!

在我們開始之前您需要什麼

在我們開始之前,讓我們確保你已經把所有的事情都安排好了:

  • 您的電腦上安裝了 Node.js
  • npm 或yarn(無論哪個都能讓你的船漂浮)

明白了嗎?偉大的!讓我們開始這場演出吧。

Faceio Authentication

設定您的專案:第一步

第 1 步:啟動您的 Next.js 項目

首先,讓我們建立 Next.js 專案。打開你的終端機並輸入這些神奇的單字:

npx create-next-app@latest faceio-app
cd faceio-app

系統會問您幾個問題。以下是如何回答這些問題:

  • 打字稿?哎呀,是的!
  • ESLint?絕對!
  • Tailwind CSS?你打賭!
  • src/目錄?不,我們很好。
  • 應用程式路由器?是的,請!
  • 自訂預設匯入別名?我們會把這個傳承下去。

第 2 步:收集你的工具

現在,讓我們去獲取我們需要的所有好東西。執行此命令來安裝我們的依賴項:

npm install @faceio/fiojs @shadcn/ui class-variance-authority clsx tailwind-merge

第三步:準備你的秘方

在專案的根目錄中建立一個名為 .env.local 的檔案。這是我們保存秘密 FACEIO 應用 ID 的地方:

NEXT_PUBLIC_FACEIO_APP_ID=your-super-secret-faceio-app-id

請記得將「your-super-secret-faceio-app-id」替換為您的實際 FACEIO 應用程式 ID。確保安全!

第四步:文件結構

您的專案結構應如下所示:

faceio-app/
├── app/
│   ├── layout.tsx
│   ├── page.tsx
│   └── components/
│       ├── FaceAuth.tsx
│       └── EmployeeDashboard.tsx
├── public/
├── .env.local
├── next.config.js
├── package.json
├── tsconfig.json
└── tailwind.config.js

第 5 步:完善 Tailwind CSS

是時候為 Tailwind 改頭換面了。使用這個奇特的設定更新您的 tailwind.config.js 檔案:

/** @type {import('tailwindcss').Config} */
module.exports = {
  darkMode: ["class"],
  content: [
    './app/**/*.{ts,tsx}',
  ],
  theme: {
    container: {
      center: true,
      padding: "2rem",
      screens: {
        "2xl": "1400px",
      },
    },
    extend: {
      colors: {
        border: "hsl(var(--border))",
        input: "hsl(var(--input))",
        ring: "hsl(var(--ring))",
        background: "hsl(var(--background))",
        foreground: "hsl(var(--foreground))",
        primary: {
          DEFAULT: "hsl(var(--primary))",
          foreground: "hsl(var(--primary-foreground))",
        },
        secondary: {
          DEFAULT: "hsl(var(--secondary))",
          foreground: "hsl(var(--secondary-foreground))",
        },
        destructive: {
          DEFAULT: "hsl(var(--destructive))",
          foreground: "hsl(var(--destructive-foreground))",
        },
        muted: {
          DEFAULT: "hsl(var(--muted))",
          foreground: "hsl(var(--muted-foreground))",
        },
        accent: {
          DEFAULT: "hsl(var(--accent))",
          foreground: "hsl(var(--accent-foreground))",
        },
        popover: {
          DEFAULT: "hsl(var(--popover))",
          foreground: "hsl(var(--popover-foreground))",
        },
        card: {
          DEFAULT: "hsl(var(--card))",
          foreground: "hsl(var(--card-foreground))",
        },
      },
      borderRadius: {
        lg: "var(--radius)",
        md: "calc(var(--radius) - 2px)",
        sm: "calc(var(--radius) - 4px)",
      },
      keyframes: {
        "accordion-down": {
          from: { height: 0 },
          to: { height: "var(--radix-accordion-content-height)" },
        },
        "accordion-up": {
          from: { height: "var(--radix-accordion-content-height)" },
          to: { height: 0 },
        },
      },
      animation: {
        "accordion-down": "accordion-down 0.2s ease-out",
        "accordion-up": "accordion-up 0.2s ease-out",
      },
    },
  },
  plugins: [require("tailwindcss-animate")],
}

建立儀表板的核心

第 1 步:製作 FaceAuth 元件

讓我們創建我們節目的明星 - FaceAuth 組件。建立一個新檔案 app/components/FaceAuth.tsx 並貼上以下程式碼:

import { useEffect } from 'react';
import faceIO from '@faceio/fiojs';
import { Button, Card, CardHeader, CardTitle, CardContent } from '@shadcn/ui';
import { useToast } from '@shadcn/ui';

interface FaceAuthProps {
  onSuccessfulAuth: (data: any) => void;
}

const FaceAuth: React.FC<FaceAuthProps> = ({ onSuccessfulAuth }) => {
  const { toast } = useToast();

  useEffect(() => {
    const faceio = new faceIO(process.env.NEXT_PUBLIC_FACEIO_APP_ID);

    const enrollNewUser = async () => {
      try {
        const userInfo = await faceio.enroll({
          locale: 'auto',
          payload: {
            email: 'employee@example.com',
            pin: '12345',
          },
        });
        toast({
          title: "Success!",
          description: "You're now enrolled in the facial recognition system!",
        });
        console.log('User Enrolled!', userInfo);
      } catch (errCode) {
        toast({
          title: "Oops!",
          description: "Enrollment failed. Please try again.",
          variant: "destructive",
        });
        console.error('Enrollment Failed', errCode);
      }
    };

    const authenticateUser = async () => {
      try {
        const userData = await faceio.authenticate();
        toast({
          title: "Welcome back!",
          description: "Authentication successful.",
        });
        console.log('User Authenticated!', userData);
        onSuccessfulAuth({
          name: 'John Doe',
          position: 'Software Developer',
          department: 'Engineering',
          photoUrl: 'https://example.com/john-doe.jpg',
        });
      } catch (errCode) {
        toast({
          title: "Authentication failed",
          description: "Please try again or enroll.",
          variant: "destructive",
        });
        console.error('Authentication Failed', errCode);
      }
    };

    const enrollBtn = document.getElementById('enroll-btn');
    const authBtn = document.getElementById('auth-btn');

    if (enrollBtn) enrollBtn.onclick = enrollNewUser;
    if (authBtn) authBtn.onclick = authenticateUser;

    return () => {
      if (enrollBtn) enrollBtn.onclick = null;
      if (authBtn) authBtn.onclick = null;
    };
  }, [toast, onSuccessfulAuth]);

  return (
    <Card className="w-full max-w-md mx-auto">
      <CardHeader>
        <CardTitle>Facial Authentication</CardTitle>
      </CardHeader>
      <CardContent className="space-y-4">
        <Button id="enroll-btn" variant="outline" className="w-full">
          Enroll New Employee
        </Button>
        <Button id="auth-btn" variant="default" className="w-full">
          Authenticate
        </Button>
      </CardContent>
    </Card>
  );
};

export default FaceAuth;

第 2 步:建立 EmployeeDashboard 元件

現在,讓我們建立員工將看到的儀表板。建立 app/components/EmployeeDashboard.tsx:

import { useState } from 'react';
import { Card, CardHeader, CardTitle, CardContent } from '@shadcn/ui';
import { Button, Avatar, Badge, Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@shadcn/ui';
import FaceAuth from './FaceAuth';

interface EmployeeData {
  name: string;
  position: string;
  department: string;
  photoUrl: string;
}

const EmployeeDashboard: React.FC = () => {
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const [employeeData, setEmployeeData] = useState<EmployeeData | null>(null);

  const handleSuccessfulAuth = (data: EmployeeData) => {
    setIsAuthenticated(true);
    setEmployeeData(data);
  };

  const mockAttendanceData = [
    { date: '2024-07-14', timeIn: '09:00 AM', timeOut: '05:30 PM' },
    { date: '2024-07-13', timeIn: '08:55 AM', timeOut: '05:25 PM' },
    { date: '2024-07-12', timeIn: '09:05 AM', timeOut: '05:35 PM' },
  ];

  return (
    <div className="space-y-6">
      {!isAuthenticated ? (
        <FaceAuth onSuccessfulAuth={handleSuccessfulAuth} />
      ) : (
        <>
          <Card>
            <CardHeader>
              <CardTitle>Employee Profile</CardTitle>
            </CardHeader>
            <CardContent className="flex items-center space-x-4">
              <Avatar className="h-20 w-20" src={employeeData?.photoUrl} alt={employeeData?.name} />
              <div>
                <h2 className="text-2xl font-bold">{employeeData?.name}</h2>
                <p className="text-gray-500">{employeeData?.position}</p>
                <Badge variant="outline">{employeeData?.department}</Badge>
              </div>
            </CardContent>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle>Quick Actions</CardTitle>
            </CardHeader>
            <CardContent className="space-y-4">
              <Button className="w-full">Check-in</Button>
              <Button className="w-full" variant="secondary">Request Leave</Button>
            </CardContent>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle>Attendance Records</CardTitle>
            </CardHeader>
            <CardContent>
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>Date</TableHead>
                    <TableHead>Time In</TableHead>
                    <TableHead>Time Out</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {mockAttendanceData.map((record, index) => (
                    <TableRow key={index}>
                      <TableCell>{record.date}</TableCell>
                      <TableCell>{record.timeIn}</TableCell>
                      <TableCell>{record.timeOut}</TableCell>
                    </TableRow>
                  ))}
                </TableBody>
              </Table>
            </CardContent>
          </Card>
        </>
      )}
    </div>
  );
};

export default EmployeeDashboard;

第三步:將它們整合在一起

最後,讓我們更新一下我們的主頁,以展示我們的辛勞。更新 app/page.tsx:

import EmployeeDashboard from './components/EmployeeDashboard';

export default function Home() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-center p-4">
      <EmployeeDashboard />
    </main>
  );
}

現在,讓我們來設定包裹整個應用程式的佈局。新增此程式碼:app/layout.tsx

import './globals.css'
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'

const inter = Inter({ subsets: ['latin'] })

export const metadata: Metadata = {
  title: 'Employee Dashboard with Facial Authentication',
  description: 'A cutting-edge employee dashboard featuring facial recognition for secure authentication and efficient workplace management.',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <header className="bg-primary text-white p-4">
          <h1 className="text-2xl font-bold">Faceio Solutions</h1>
        </header>
        <main className="container mx-auto p-4">
          {children}
        </main>
        <footer className="bg-gray-100 text-center p-4 mt-8">
          <p>&copy; 2024 Faceio . All rights reserved.</p>
        </footer>
      </body>
    </html>
  )
}

這種佈局就像房子的框架 - 它為您的整個應用程式提供結構。它包括帶有您公司名稱的標題、將顯示儀表板的主要內容區域和頁腳。另外,它還利用元數據設定了一些 SEO 魔法!

FACEIO 整合的關鍵隱私和安全實踐

隱私設計

  • 使用存取控制、使用者同意和選擇退出選項來保護隱私。

有意義的同意

  • 確保使用者了解資料收集。
  • 提供對資料的選擇和控制的自由。
  • 允許隨時撤銷同意和刪除資料。

最佳實踐

  • 獲得明確且適當的同意,尤其是對未成年人。
  • 使同意請求易於找到和理解。
  • 避免自動註冊和未經授權的註冊。
  • 收集生物辨識資料前通知使用者。
  • 遵守法律資料隱私要求。

資料安全

  • 刪除帳戶時刪除使用者資料。
  • 保持強有力的資料保留和處理實務。
  • 定期實施並檢討安全保障措施。

更多詳情,請參閱FACEIO最佳實務。

FACEIO 整合的關鍵安全注意事項

安全設計

  • 應用程式安全對於維護使用者信任至關重要。
  • 遵循 FACEIO 的安全最佳實踐來降低風險。

核心安全功能

  1. 拒絕弱 PIN

    • 防止 0000 或 1234 等弱 PIN。
    • 預設:否。
  2. 防止重複註冊

    • 阻止用戶多次註冊。
    • 預設:否。
  3. 防止深度贗品

    • 偵測並阻止欺騙嘗試。
    • 預設:否。
  4. 禁止未成年人報名

    • 阻止 18 歲以下的用戶註冊。
    • 預設:否。
  5. 需要 PIN 碼才能驗證

    • 每次驗證都需要 PIN 碼。
    • 預設:是。
  6. 強制使用唯一的 PIN

    • 確保每位使用者的 PIN 碼是唯一的。
    • 預設:否。
  7. 忽略被遮蔽的臉

    • 丟棄光線不佳或部分遮擋的臉。
    • 預設:是。
  8. 拒絕遺失的標頭

    • 阻止沒有正確 HTTP 標頭的實例化。
    • 預設:是。
  9. 限制實例化

    • 限制特定領域和國家。
    • 預設:否。
  10. 啟用 Webhooks

    • 通知您的後端 FACEIO 事件。
    • 預設:否。

更多詳細信息,請參閱 FACEIO 安全最佳實踐。

實際應用:您可以在哪裡使用它?

現在我們已經建立了這個很棒的儀表板,您可能想知道,「我可以在現實世界中的哪裡使用它?」好吧,讓我告訴你,可能性是無限的!這裡只是一些想法:

  1. 辦公室管理:告別老式打孔卡!該系統可以徹底改變您追蹤出勤、控制對辦公室不同區域的存取以及管理員工資訊的方式。

  2. 安全系統:想像一個世界,您的辦公室位於諾克斯堡,但沒有任何麻煩。此臉部辨識系統可以成為強大安全協議的基石。

  3. 客戶服務亭:想像一下 - 客戶走到服務亭,它立即識別出他們,並提供個人化服務。這不再是科幻小說了!

接下來是什麼?天空才是極限!

恭喜你,技術奇才!您剛剛建立了一個具有臉部身份驗證功能的尖端員工儀表板。但為什麼停在這裡呢?該系統的優點在於其彈性。以下是一些將其提升到新水平的想法:

  • 對重要更新實施即時通知
  • 為 HR 加入詳細的報告功能
  • 與薪資或專案管理工具等其他系統整合

請記住,在科技世界中,唯一的限制是你的想像力(也許還有你的咖啡因攝取量)。

那麼,你覺得怎麼樣?您準備好將您的工作場所帶入未來了嗎?嘗試這個項目,讓我知道進展如何。我很想聽聽您的經歷、您添加的任何很酷的功能,或您在過程中面臨的任何挑戰。

祝您編碼愉快,願您的臉部辨識永遠不會將您誤認為是辦公室植物!

以上是使用臉部身份驗證建立安全的員工儀表板:綜合 Next.js 教程的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn