Next.js 10 및 Vercel에서 간단하고 안전한 암호 인증 구현

18811 단어 passphraseauthnextjs
나는 현재 내 personal website에 대한 일부 개인 사례 연구를 게시하는 중이며 암호 보안을 추가하는 간단한 방법을 원했습니다.

Next.js에서 인증을 처리하는 몇 가지notable libraries가 있지만 이러한 라이브러리에서 실제로 처리되지 않는 두 가지 요구 사항이 있습니다.
  • 암호 인증이 아닌 암호 보안을 원했습니다. 비밀번호 인증은 일반적으로 이메일과 연결되어 있으며 ID를 설정해야 합니다. 내가 원하는 방법은 내가 사용자에게 제공했을 간단한 암호에 의존합니다.
  • 환경 변수에 암호를 저장하려고 했습니다. 그것들을 GitHub에 커밋하지 않고 Prism(내 콘텐츠의 나머지 부분이 있는 곳)에 저장하는 것이 절대적으로 이상적일 것입니다.
  • 사용자의 컴퓨터에 쿠키를 저장하고 싶지 않습니다. 현재 쿠키 없는 상태를 유지하는 것을 목표로 하고 있기 때문에 모든 웹사이트에서 Fathom Analytics을 사용합니다.

  • 약간의 고민 끝에 공유할 수 있는 비교적 간단한 솔루션을 찾았습니다!

    먼저 프런트 엔드입니다. 기본적으로 사례 연구에 대한 액세스는 상태와 같은 간단한 것으로 제어할 수 있습니다.

    import type { GetStaticProps, GetStaticPaths } from 'next';
    import { useState } from 'react';
    
    type ICaseStudy = {
      uid: string;
    }
    
    const CaseStudy = ({ uid }: ICaseStudy) => {
      const [authenticated, setAuthenticated] = useState<boolean>(false);
      const [passphrase, setPassphrase] = useState<string>('');
      const [loading, setLoading] = useState<boolean>(false);
      const [data, setData] = useState<any>(null);
    
      return (
        <form className={`${styles.form} ${loading ? styles.loading : ""}`}
        onSubmit={authenticate}>
          <label className={styles.label} htmlFor="passphrase">
            Enter passphrase
          </label>
          <input
            required
            id="passphrase"
            className={styles.input}
            type="text"
            placeholder="Enter a passphrase"
            value={value}
            onChange={({ target }) => setPassPhrase(target.value)}
          />
          <button aria-label="Sign up" type="submit" className={styles.button}>
            &rarr;
          </button>
        </form>
      );
    }
    
    export const getStaticProps: GetStaticProps = async ({ params }) => {
      const { uid } = params!;
    
      return {
        props: {
          uid,
        },
      };
    }
    
    export const getStaticPaths: GetStaticPaths = async () => {
      const caseStudies = await queryAt('document.type', 'case_study');
      const paths = caseStudies.map(({ uid }) => (
        { params: { uid } }
      ));
    
      return {
        paths,
        fallback: false,
      }
    }
    


    여기서 주목해야 할 두 가지 사항: 첫째, 나는 getStaticProps에서 정상적으로 프리즘 데이터를 가져올 수 없었습니다. 이는 Next.js가 데이터를 문자열화하여 원시 HTML로 출력하기 때문입니다. 즉, 오른쪽 클릭 > 소스 보기 방법을 아는 사람이라면 누구나 사례 연구 데이터를 볼 수 있습니다.

    둘째, 기본적으로 암호를 제외하고는 동일합니다. 암호 확인은 서버 측에서 이루어져야 하므로 양식 제출을 사용합니다. React에서 암호의 유효성을 검사하면 암호가 HTML 소스 어딘가에 나타납니다.

    다음은 간단한 인증 기능입니다.

    import type { FormEvent } from 'react';
    import { queryAt } from "../../utils/prismic";
    
    async function authenticate(event: FormEvent) {
      event.preventDefault();
      setLoading(true);
    
      try {
        const response = await fetch("/api/passphrase", {
          method: "post",
          body: JSON.stringify({ uid, passphrase }),
        });
    
        const body = await response.json();
    
        if (!body.success) {
          throw new Error(body.message);
        }
    
        const newData = await queryAt('my.case_study.uid', uid);
    
        setData(newData.data);
        setAuthenticated(true);
      } catch (error: any) {
        window.alert("Sorry, wrong password.");
      } finally {
        setLoading(false);
      }
    }
    


    여기서 우리는 단순히 UID(사례 연구 슬러그) 및 암호를 사용하여 /api/passphrase에서 Next.js API 경로를 조회합니다. 성공하면 Prismic에서 데이터를 가져옵니다(작은 Prism 유틸리티 라이브러리 사용).

    다음으로 암호를 확인하는 API 경로:

    export default async function handler(req, res) {
      res.setHeader("Content-Type", "application/json");
    
      try {
        const { uid, passphrase } = JSON.parse(req.body);
    
        if (!uid || !passphrase) {
          throw new Error('Please provide a passphrase.');
        }
    
        const secret = process.env[`PASSPHRASE_${uid.toUpperCase()}`];
    
        if (!secret) {
          throw new Error('Passphrase has not been set up for this project.');
        }
    
        if (secret !== passphrase) {
          throw new Error("Passphrase is not correct.");
        }
    
        res.statusCode = 200;
        res.json({ success: true }));
      } catch (error) {
        res.statusCode = 500;
        res.json({ message: error.message }));
      }
    }
    


    여기에서 우리는 UID와 암호를 받은 다음 UID를 기반으로 적절한 환경 변수를 가져옵니다. 약간의 오류 확인 후 암호를 확인한 다음 브라우저에 성공 메시지를 반환할 수 있습니다.

    마지막으로 Vercel로 이동하여 설정에 해당 환경 변수를 입력하십시오.



    그리고 그게 다야! Next.js에서 간단한 암호 확인. 어쨌든 요청 하이재킹 및 성공 메시지 반환과 같은 보안 문제를 놓친 적이 있다고 확신하지만 지금은 할 것입니다.

    그것을 개선하는 방법에 대한 팁이 있으면 알려주세요!

    좋은 웹페이지 즐겨찾기