Aws Amplify, ReactJs 및 Tailwind CSS를 사용하여 흐름 검증

Source code for this post can be found here


얼마 전까지만 해도 한 응용 프로그램을 위해 완전한 신분 검증 흐름을 작성하는 것은 많은 노력과 신중을 들여야 했던 작업이었다. 지금은 Aws amplify와 현대 UI 라이브러리(exp:ReactJS) 등 도구가 생겨서 이 기본 기능을 구축하는 데 몇 시간밖에 걸리지 않았다.
먼저 create react app로 애플리케이션을 만듭니다.

npx create-react-app my-login-app


환경과 선결 조건


다른 모든 설정을 시작하기 전에 다음 장치가 설치되어 있는지 확인합니다.
  • 노드js v10.x 이상
  • 유효하고 확인된 AWS 계정
  • AWS Amplify 프로젝트 설치 및 초기화


    NPM
    $ npm install -g @aws-amplify/cli

    cURL (Mac & Linux)
    curl -sL https://aws-amplify.github.io/amplify-cli/install | >bash && $SHELL

    cURL (Windows)
    curl -sL https://aws-amplify.github.io/amplify-cli/install->win -o install.cmd && install.cmd


    이제 자격 증명을 사용하여 CLI를 구성합니다.
    만약 당신이 이 설정 과정의 연습을 보고 싶다면, 영상을 보고 어떻게 설정을 하는지 보여줄 수 있다.

    $ amplify configure


    - Specify the AWS Region: us-east-1 || us-west-2 || eu-central-1
    - Specify the username of the new IAM user: your-user-name
    > In the AWS Console, click Next: Permissions, Next: Tags, Next: Review, & Create User to create the new IAM user. Then return to the command line & press Enter.
    - Enter the access key of the newly created user:   
    ? accessKeyId: (<YOUR_ACCESS_KEY_ID>)  
    ? secretAccessKey: (<YOUR_SECRET_ACCESS_KEY>)
    - Profile Name: your-user-name
    
    실행: > $amplify init를 통해 새로운 확대 설정을 초기화합니다
    ? Enter a name for the project myloginapp
    ? Enter a name for the environment dev
    ? Choose your default editor: Visual Studio Code
    ? Choose the type of app that you're building javascript
    Please tell us about your project
    ? What javascript framework are you using react
    ? Source Directory Path:  src
    ? Distribution Directory Path: build
    ? Build Command:  npm run-script build
    ? Start Command: npm run-script start
    Using default provider  awscloudformation
    
    For more information on AWS Profiles, see:
    https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html
    
    ? Do you want to use an AWS profile? (Y/n) y
    ? Please choose the profile you want to use: your-user-name
    
    이제 src/index.js 파일을 열고 다음 줄을 추가합니다.
    import App from './App';
    ....
    import Amplify from 'aws-amplify';
    import awsconfig from './aws-exports';
    Amplify.configure(awsconfig);
    
    
    이제 인증 서비스를 추가해야 합니다. Amplify는 Amazon Cognito를 주요 인증 공급자로 사용하고 등록, 인증, 계정 복구 및 기타 작업을 처리하는 모든 도구를 제공합니다.
    다음 단계를 따르겠습니다.

    amplify add auth


    ❯ Default configuration 
      Default configuration with Social Provider (Federation) 
      Manual configuration 
      I want to learn more. 
    
     How do you want users to be able to sign in? (Use arrow keys)
    ❯ Username 
      Email 
      Phone Number 
      Email or Phone Number 
      I want to learn more. 
    
     Do you want to configure advanced settings? (Use arrow keys)
    ❯ No, I am done. 
      Yes, I want to make some additional changes. 
    
    
    마지막으로, 우리는 우리의 진도를 저희 계정으로 전송할 수 있습니다. 이로써 AWS는 이 점을 알 수 있습니다. 이렇게 하면 amplify push 귀하의 모든 로컬 백엔드 자원을 구축하고 클라우드에 제공할 수 있습니다.

    순풍 CSS


    우리는 CSS에 너무 많은 시간을 들이지 않고 다음 명령을 실행하여 신속하게 설치할 수 있는 멋진 디자인을 원합니다Tailwind CSS.

    npm install tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9

    package.json 파일에서 scripts 객체에 다음 행을 추가합니다.
      "scripts": {
        "build:tailwind": "tailwindcss build src/tailwind.css -o src/tailwind.generated.css",
        "prestart": "npm run build:tailwind",
        "prebuild": "npm run build:tailwind",
    .....
    
    src 폴더 src/tailwind.css 에 새 파일을 만듭니다.tailwind 기본 스타일을 가져오고 다음 줄을 추가합니다.
    @tailwind base;
    @tailwind components;
    @tailwind utilities;
    
    이 두 단계는 새 tailwind.generated.css 파일을 만들고, 전체 프로그램에서tailwind 클래스를 사용할 수 있도록 App.js 파일을 가져와야 합니다.
    import './App.css';
    import './tailwind.generated.css';
    
    마지막으로, 우리는 이렇게 많은 코드만 남겨서 App.css 파일을 정리합시다.
    .App {
      text-align: center;
    }
    
    .App-header {
      min-height: 100vh;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      font-size: calc(10px + 2vmin);
    }
    

    반응 라우터


    react 라우터가 설치되지 않도록 라우터 "시스템"의 도움말이 필요합니다.

    npm i react-router && react-router-dom


    또한 업데이트App.js를 통해 다음과 같은 내용을 확인할 수 있습니다.
    import React from 'react';
    import {
      BrowserRouter as Router,
      Switch,
      Route,
    } from "react-router-dom";
    import './App.css'
    
    function App() {
      return (
        <div className="App">
          <header className="App-header">
            <Router>
              <Switch>
                <div>
                  My app
                </div>
             </Switch>
            </Router>
          </header>
        </div>
      )
    }
    
    export default App
    
    
    component/Register.js 파일에서auth 흐름의 첫 번째 화면을 만들 때 다음 코드를 추가합니다.
    import React, { useState } from 'react';
    import { Auth } from 'aws-amplify';
    import Input from '../../common/Input';
    import { Link, useHistory } from 'react-router-dom';
    
    const Register = () => {
      let history = useHistory();
      const [user, setUser] = useState({ username: '', password: '', });
    
      const handleInputChange = (event, keyName) => {
        event.persist();
        setUser((user) => {
          return { ...user, [keyName]: event.target.value }
        })
      }
    
      const signUp = async () => {
        try {
          await Auth.signUp({
            username: user.username,
            password: user.password,
            attributes: {
              email: user.username,
            }
          });
          history.push("/confirm-register");
        } catch (error) {
          console.log('error', error);
        }
      }
    
      return (
        <div className="container w-4/12 w-medium">
          <div className="bg-white shadow-xl rounded px-12 pt-6 pb-8 mb-4">
            <h3 className="text-lg text-gray-700">Register</h3>
            <Input
              labelName='Email:'
              value={user.username}
              handleInputChange={(e) => handleInputChange(e, 'username')}
            />
            <Input
              labelName='Password:'
              type="password"
              value={user.password}
              handleInputChange={(e) => handleInputChange(e, 'password')}
            />
            <div className="flex items-center justify-between">
              <button
                className="mt-4 mb-4 w-full sm:w-auto border border-transparent px-6 py-3 text-base font-semibold leading-snug bg-gray-900 text-white rounded-md shadow-md hover:bg-gray-800 focus:outline-none focus:bg-gray-800 transition ease-in-out duration-150 hover:bg-gray-600"
                type="button"
                onClick={() => signUp()}
              >
                Send
              </button>
            </div>
            <div className="w-full">
              <hr />
              <p className="text-gray-700 pb-2 pt-2 text-sm">You already habe an account?</p>
              <Link
                to={{
                  pathname: '/log-in'
                }}
                className="pt-2 text-sm text-blue-500 hover:text-blue-600"
              >
                Long in
              </Link>
            </div>
          </div>
        </div>
      )
    }
    
    export default Register;
    
    작고 실용적인 입력 구성 요소를 위한 common/Input.js 파일을 만듭니다.
    
    import React from 'react';
    
    const Input =({ labelName, value, type="text", handleInputChange }) => {
      return (
        <div className="pb-15">
          <label className="block text-gray-700 text-sm font-bold mb-2">{labelName}</label>
          <input
            type={type}
            className="account-input bg-white focus:outline-none focus:shadow-outline border border-gray-300 rounded-sm py-2 px-2 block w-full appearance-none leading-normal"
            value={value}
            onChange={handleInputChange}
          />
        </div>
      )
    }
    
    export default Input;
    
    
    사용자가 가입 상세 정보 (이메일 및 비밀번호) 를 추가한 후, 계정을 활성화하기 위해 유일한 코드가 있는 확인 이메일을 받을 준비가 되지 않았습니다.이 단계를 위해 component/ConfirmRegister 화면을 만듭니다.
    import { Auth } from 'aws-amplify';
    import React, { useState } from 'react';
    import Input from '../../common/Input';
    import { Link, useHistory } from "react-router-dom";
    
    const ConfirmRegister = () => {
      let history = useHistory();
      const [user, setUser] = useState({ username: '', authenticationCode: '', });
    
      const handleInputChange = (event, keyName) => {
        event.persist();
        setUser((user) => {
          return { ...user, [keyName]: event.target.value }
        })
      }
    
      const confirmSignUp = async () => {
        try {
          await Auth.confirmSignUp(user.username, user.authenticationCode);
          console.log('success confirm sign up');
          history.push('./log-in')
        } catch (error) {
          console.log('error', error);
        }
      }
    
      return (
        <div className="container w-4/12 w-medium">
          <div className="bg-white shadow-xl rounded px-12 pt-6 pb-8 mb-4">
            <h3 className="text-lg text-gray-700">Confirm your account</h3>
            <Input
              labelName='Email:'
              value={user.username}
              handleInputChange={(e) => handleInputChange(e, 'username')}
            />
            <Input
              labelName='Code:'
              value={user.authenticationCode}
              handleInputChange={(e) => handleInputChange(e, 'authenticationCode')}
            />
            <button
              onClick={() => confirmSignUp()}
              className="mt-4 mb-4 w-full sm:w-auto border border-transparent px-6 py-3 text-base font-semibold leading-snug bg-gray-900 text-white rounded-md shadow-md hover:bg-gray-800 focus:outline-none focus:bg-gray-800 transition ease-in-out duration-150 hover:bg-gray-600"
            >
              Confirm
            </button>
            <div>
              <Link
                to={{
                  pathname: '/register'
                }}
                className="pt-2 text-sm text-blue-500 hover:text-blue-600"
              >
                Back
              </Link>
            </div>
          </div>
        </div>
      )
    }
    
    export default ConfirmRegister;
    
    
    저희 프로그램은 새 계정을 등록할 준비가 되어 있습니다. 귀하는 개인 전자메일을 사용할 필요가 없습니다. 이 뛰어난 10 min email 사이트는 귀하께 임시 계정을 제공할 수 있습니다.
    이제 사용자를 등록했으므로 다음 코드를 추가하여 components/Login.js 페이지를 만듭니다.
    import { Auth } from 'aws-amplify';
    import React, { useState } from 'react';
    import { useHistory, Link } from "react-router-dom";
    import Input from './common/Input';
    
    const LogIn = () => {
      let history = useHistory();
      const [user, setUser] = useState({ username: '', password: '' });
    
      const handleInputChange = (event, keyName) => {
        event.persist();
        setUser((user) => {
          return { ...user, [keyName]: event.target.value }
        })
      }
    
      const logIn = async () => {
        try {
          await Auth.signIn({
            username: user.username,
            password: user.password,
          });
          history.push('./home')
        } catch (error) {
          console.error('error', error);
        }
      }
      return (
        <div className="container w-4/12 w-medium">
          <div className="bg-white shadow-xl rounded px-12 pt-6 pb-8 mb-4">
            <h3 className="text-lg text-gray-800 mb-2">Log In</h3>
            <Input
              labelName='Email:'
              value={user.username}
              handleInputChange={(e) => handleInputChange(e, 'username')}
            />
            <Input
              labelName='Password:'
              type="password"
              value={user.password}
              handleInputChange={(e) => handleInputChange(e, 'password')}
            />
            <div className="flex items-center justify-between">
              <button
                onClick={() => logIn()}
                className="mt-4 mb-4 w-full sm:w-auto border border-transparent px-6 py-3 text-base font-semibold leading-snug bg-gray-900 text-white rounded-md shadow-md hover:bg-gray-800 focus:outline-none focus:bg-gray-800 transition ease-in-out duration-150 hover:bg-gray-600"
              >
                Log in
              </button>
            </div>
            <div className="w-full">
              <hr />
              <p className="text-gray-700 pb-2 pt-2 text-sm">Don't have an account?</p>
              <Link
                to={{
                  pathname: '/register'
                }}
                className="pt-2 text-sm text-blue-500 hover:text-blue-600"
              >
                Register
              </Link>
            </div>
          </div>
        </div>
      )
    }
    
    export default LogIn;
    
    사용자가 로그인한 후에, 우리는 최종적으로 그들에게 홈페이지에 접근할 수 있는 권한을 부여할 수 있다.
    간단한 components/Home 페이지 구성 요소를 만듭니다.
    import React from 'react'
    import Auth from '@aws-amplify/auth';
    import { Link } from "react-router-dom";
    
    const Home = () => {
      let signOut = async() => {
        await Auth.signOut();
        console.log("Sign out succesfully")
      }
      return (
        <div>
          <h2 className="px-3 mb-3 lg:mb-3 uppercase tracking-wide font-semibold text-sm lg:text-lg text-gray-900">
            Home page
          </h2>
          <div className="ml-3 text-base">
            <Link
              to={{
                pathname: '/log-in',
              }}
              onClick={signOut}
              className="pt-2 text-sm text-gray-500 hover:text-gray-600"
            >
              Log out
            </Link>
          </div>
        </div>
      )
    }
    
    export default Home
    
    
    이러한 모든 라우팅을 함께 배치하고 react router 도움말 아래 페이지 간 연결을 설정하면 App.js 파일을 다음과 같이 변경할 수 있습니다.
    import React from 'react';
    import {
      BrowserRouter as Router,
      Switch,
      Route,
    } from "react-router-dom";
    import Login from './components/Login';
    import Register from './components/Register';
    import Home from './components/Home';
    import ConfirmRegister from './components/ConfirmRegister';
    
    import './App.css';
    import './tailwind.generated.css';
    
    function App() {
      return (
        <div className="App">
          <header className="App-header">
            <Router>
              <Switch>
                <Route component={Home} path="/home" />
                <Route component={ConfirmRegister} path="/confirm-register" />
                <Route component={Login} path="/log-in" />
                <Route component={Register} path="/" />
              </Switch>
            </Router>
          </header>
        </div>
      )
    }
    
    export default App
    
    
    마지막으로 우리는 우리의 응용 프로그램을 테스트하고 계정을 만들며 로그인할 수 있습니다!npm start 또는 yarn start를 실행하도록 하겠습니다. 등록 페이지http://localhost:3000는 다음과 같이 첫 번째 페이지가 되어야 합니다.

    하지만 잠깐만, 이 프로그램은 아직 완전히 완성되지 않았어!누군가가 실제로 홈페이지http://localhost:3000/home로 내비게이션을 할 수 있어 계좌나 신분 검증이 필요 없으니 큰일이다!
    이 문제를 해결하고 프로그램을 보호하며 새로운 components/PrivateRoute 파일을 만들 수 있도록 개인 루트를 만듭니다.
    
    import React, { useState, useEffect }  from 'react';
    import { Redirect, Route } from "react-router-dom";
    import { Auth } from 'aws-amplify';
    import Homepage from './Home'
    
    const PrivateRoute = ({ children, ...rest }) => {
      const [signInUser, setSignInUser] = useState(null);
      const [isLoading, setIsLoading] = useState(true);
    
      useEffect(() => {
        let getUser = async() => {
          try {
            let user = await Auth.currentAuthenticatedUser();
            await setSignInUser(user);
            setIsLoading(false);
          } catch (error) {
            setIsLoading(false);
            console.log(error)        
          }
        }
        getUser();
      },[]);
    
      if(isLoading) {
        return <p>...Loading</p>
      }
      return (
        <Route {...rest} render={({ location }) => {
          return signInUser? <Homepage/>
            : <Redirect to={{
                pathname: '/log-in',
                state: { from: location }
              }} />
        }} />
      )
    }
    
    export default PrivateRoute;
    
    App.js 파일에서 개인 루트 구성 요소로 홈 페이지를 포장합니다
    .....
    import PrivateRoute from './components/PrivateRoute';
    
    import './App.css';
    import './tailwind.generated.css';
    
    function App() {
      return (
        <div className="App">
          <header className="App-header">
            <Router>
              <Switch>
                <PrivateRoute path="/home">
                </PrivateRoute>
                <Route component={ConfirmRegister} path="/confirm-register" />
                <Route component={Login} path="/log-in" />
                <Route component={Register} path="/" />
              </Switch>
            </Router>
          </header>
        </div>
      )
    }
    
    export default App
    

    결론


    AWS amplify and react 덕분에 사용자 정의 인증 프로세스를 사용할 수 있으며 탐색 보안 계층(전용 경로)까지 갖춰져 있습니다.

    대기 사항


    절차에 암호를 잊어버리는 기능을 추가해서 공부를 할 수 있습니다. 문제가 있으면 댓글로 알려주십시오.
    만약 다른 사람들이 이 글을 읽어야 한다고 생각한다면.트위터, 공유하고 관심 가져주세요.

    좋은 웹페이지 즐겨찾기