본문 바로가기

클라우드/AWS

인증과 권한

 

⇒ 80페이지의 JSON 내용과 동일

 




P88 Lambda 함수가 오류로 인해 비정상적으로 종료된 회수를 추적

버지니아 북부(us-east-1) 리전에서 실습











P91 serverless-video-upload 버킷의 로그를 저장

S3 로그는 버킷 이름, 요청시간, 동작, 응답 상태와 같은 정보를 저장

 

#1 로그 파일을 저장할 버킷을 생성



#2 servless-video-upload 버킷의 로그를 serverless-video-logs 버킷에 저장

대상 접두사 = 폴더(디렉터리) 개념




P92 일정 간격으로 세 개 이상의 람다 함수 오류가 발생하면 이메일 경보를 발송

#1 주제 및 이메일 구독 생성

 

#2 경보 생성

 

#3 잘못된 값(오류가 발생할 수 있는 값)으로 람다 함수를 실행 (3번 이상 테스트)

 

#4 경고 메일 확인




P96 S3 버킷에서 발생하는 데이터 이벤트를 모으는 추적을 생성

 

 

P99 CloudWatch 결제 경보 생성



간이 월 비용 계산기 (simple monthly caculator) 

https://calculator.s3.amazonaws.com/index.html




Stateful ⇒ 웹 서버

클라이언트의 상태 정보를 유지하는 서버

⇒ 세션을 이용해서 구현



Stateless

⇒ 서버로 부터 발급 받은 토큰을 이용해서 신분을 증명









P114 24-Hour Video 웹 사이트 생성

실습에서는 Bootstrp + jQuery 기반으로 작성

 

실제 서비스 환경에서는 SPA 형태의 웹 애플리케이션을 구현 ⇒ Agular, React, … JavaScript Framework을 이용해서 구현



#1 프로젝트 생성

c:\Users\myanj\Downloads> cd /

 

c:\> cd serverless

 

c:\serverless> mkdir 24-hour-video

 

c:\serverless> cd 24-hour-video

 

c:\serverless\24-hour-video> npm init -y

Wrote to c:\serverless\24-hour-video\package.json:

 

{

  "name": "24-hour-video",

  "version": "1.0.0",

  "description": "",

  "main": "index.js",

  "scripts": {

    "test": "echo \"Error: no test specified\" && exit 1"

  },

  "keywords": [],

  "author": "",

  "license": "ISC"

}

 

c:\serverless\24-hour-video> npm install local-web-server --save-dev

 

c:\serverless\24-hour-video> type package.json

{

  "name": "24-hour-video",

  "version": "1.0.0",

  "description": "",

  "main": "index.js",

  "scripts": {

    "test": "echo \"Error: no test specified\" && exit 1"

  },

  "keywords": [],

  "author": "",

  "license": "ISC",

  "devDependencies": {

    "local-web-server": "^4.2.1"

  }

}

 

package.json 파일에 start 스크립트를 추가

c:\serverless\24-hour-video\package.json

{

  "name": "24-hour-video",

  "version": "1.0.0",

  "description": "",

  "main": "index.js",

  "scripts": {

    "start": "ws", 

    "test": "echo \"Error: no test specified\" && exit 1"

  },

  "keywords": [],

  "author": "",

  "license": "ISC",

  "devDependencies": {

    "local-web-server": "^4.2.1"

  }

}



#2 UI 템플릿 다운로드

http://www.initializr.com/



#3 다운로드 받은 템플릿 파일을 프로젝트 폴더(c:\serverless\24-hour-video\)로 압축 해제



#4 웹 서버 실행 및 확인

c:\serverless\24-hour-video> npm start




Auth0 구성 (P116)

#1 https://auth0.com/ 사이트에 회원 가입

  • TENANT DOMAIN에 본인이 기억할 수 있는 이름을 입력

  • REGION을 US로 설정

 

#2 Application 생성

Applications 메뉴 > CREATE APPLICATION 버튼 클릭

 



#3 Connection > Socail 메뉴에서 제공하는 소셜 로그인  사이트에 앱 추가 후 호출에 필요한 ID와 Secret를 확인

 

#4 TRY CONNECTION 기능을 이용해서 쇼셜 로그인 후 사용자 정보가 JSON 형태로 제공되는 것을 확인




웹 사이트에 Auth0를 연결 (P119)

 

#1 Auth0 Lock 스크립트, Domain, Client ID 등을 확인

 





#2 웹 페이지에 로그인, 로그아웃, 사용자 프로필 기능 추가

 

c:\serverless\24-hour-video\index.html 파일에 Auth0 Lock 스크립트 추가

                            :

        <script src="js/vendor/bootstrap.min.js"></script>


        

 

        

        <script src="js/main.js"></script>

                            :

 

c:\serverless\24-hour-video\js\config.js 파일 생성

var configConstants = {

    auth0: {

        // auth0.com > Applications > 24-Hour-Video > Settings 에서 확인

        domain: 'naanjini.us.auth0.com', 

        clientId: 'ToTAPXsB30Hg0Wo0JbQ1Vd0oBJaV-7P2RazJEBxGVNlHjCYtEhIrN-XmXE8E6Kz2'

    }

};

 

c:\serverless\24-hour-video\index.html 파일에 로그인, 로그아웃, 사용자 프로필 버튼을 추가

<!doctype html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang=""> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8" lang=""> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9" lang=""> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang=""> <!--<![endif]-->
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <title></title>
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="apple-touch-icon" href="apple-touch-icon.png">
 
        <link rel="stylesheet" href="css/bootstrap.min.css">
        <style>
            body {
                padding-top: 50px;
                padding-bottom: 20px;
            }
        </style>
        <link rel="stylesheet" href="css/bootstrap-theme.min.css">
        <link rel="stylesheet" href="css/main.css">
 
        <script src="js/vendor/modernizr-2.8.3-respond-1.4.2.min.js"></script>
    </head>
    <body>
        <!--[if lt IE 8]>
            <p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
        <![endif]-->
    <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Project name</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
 
          <!--
          <form class="navbar-form navbar-right" role="form">
            <div class="form-group">
              <input type="text" placeholder="Email" class="form-control">
            </div>
            <div class="form-group">
              <input type="password" placeholder="Password" class="form-control">
            </div>
            <button type="submit" class="btn btn-success">Sign in</button>
          </form>
          -->
          <!-- 121 페이지 참조 -->
          <div class="navbar-form navbar-right">
            <button id="user-profile" class="btn btn-default">
              <img id="profilepicture" />&nbsp;<span id="profilename"></span>
            </button>
            <button id="auth0-login" class="btn btn-success">Sign in</button>
            <button id="auth0-logout" class="btn btn-success">Sign out</button>
          </div>
 
        </div><!--/.navbar-collapse -->
      </div>
    </nav>
 
    <!-- Main jumbotron for a primary marketing message or call to action -->
    <div class="jumbotron">
      <div class="container">
        <h1>Hello, world!</h1>
        <p>This is a template for a simple marketing or informational website. It includes a large callout called a jumbotron and three supporting pieces of content. Use it as a starting point to create something more unique.</p>
        <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more &raquo;</a></p>
      </div>
    </div>
 
    <div class="container">
      <!-- Example row of columns -->
      <div class="row">
        <div class="col-md-4">
          <h2>Heading</h2>
          <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>
          <p><a class="btn btn-default" href="#" role="button">View details &raquo;</a></p>
        </div>
        <div class="col-md-4">
          <h2>Heading</h2>
          <p>Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Etiam porta sem malesuada magna mollis euismod. Donec sed odio dui. </p>
          <p><a class="btn btn-default" href="#" role="button">View details &raquo;</a></p>
       </div>
        <div class="col-md-4">
          <h2>Heading</h2>
          <p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>
          <p><a class="btn btn-default" href="#" role="button">View details &raquo;</a></p>
        </div>
      </div>
 
      <hr>
 
      <footer>
        <p>&copy; Company 2015</p>
      </footer>
    </div> <!-- /container -->        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
        <script>window.jQuery || document.write('<script src="js/vendor/jquery-1.11.2.min.js"><\/script>')</script>
 
        <script src="js/vendor/bootstrap.min.js"></script>
 
        <script src="https://cdn.auth0.com/js/lock/11.27/lock.min.js"></script>
        <script src="js/config.js"></script>
        <script src="js/user-controller.js"></script>
        <script src="js/main.js"></script>
 
        <!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
        <script>
            (function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
            function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
            e=o.createElement(i);r=o.getElementsByTagName(i)[0];
            e.src='//www.google-analytics.com/analytics.js';
            r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
            ga('create','UA-XXXXX-X','auto');ga('send','pageview');
        </script>
    </body>
</html>

 

c:\serverless\24-hour-video\user-controller.js 파일 생성

// 122 페이지 참고
// 로그인/로그아웃 버튼을 클릭했을 때 액션을 처리 
var userController = {
    data: {
        auth0Lock: null,
        config: null
    }, 
    uiElements: {
        loginButton: null,
        logoutButton: null, 
        profileButton: null, 
        profileNameLabel: null,
        profileImage: null
    }, 
    init: function (config) {
        var that = this;
 
        this.uiElements.loginButton = $('#auth0-login');        // document.getElementById("auth0-login")
        this.uiElements.logoutButton = $('#auth0-logout');
        this.uiElements.profileButton = $('#user-profile');
        this.uiElements.profileNameLabel = $('#profilename');
        this.uiElements.profileImage = $('#profilepicture');
 
        this.data.config = config;
        this.data.auth0Lock = new Auth0Lock(config.auth0.clientId, config.auth0.domain);
 
        //  로컬 스토리지에서 userToken 이름의 값을 가져와서 idToken 변수에 저장
        //  동일한 이름의 로컬 스토리지 변수가 없으면 null을 반환
        var idToken = localStorage.getItem('userToken');
        if (idToken) {
            this.configureAuthenticatedRequests();
            //  auth0.com에 토큰(로컬 스토리지에 저장된 값)에 해당하는 사용자의 정보를 조회
            this.data.auth0Lock.getProfile(idToken, function (err, profile) {
                if (err) {
                    return alert('프로필을 가져오는데 실패했습니다. ' + err.message);
                }
                that.showUserAuthenticationDetails(profile);
            });
        }
        this.wireEvents();
    },
    configureAuthenticatedRequests: function() {
        //  https://api.jquery.com/jquery.ajaxsetup/
        //  ajax 통신을 할 때 선행되어야 할 작업을 기술
        $.ajaxSetup({
            'beforeSend': function (xhr) {
                //  요청 헤더에 아래 형식의 요청 헤더를 추가
                //  Authorization: Bearer 로컬_스토리지에_저장된_토큰값 
                xhr.setRequestsHeader('Authorization', 'Bearer ' + localStorage.getItem('userToken'));
            }
        })
    }, 
    showUserAuthenticationDetails: function(profile) {
        console.log(profile);   // 로그인 사용자의 정보가 JSON 형태로 저장
 
        //  프로필 정보가 있으면 프로필 사진과 별명을 화면에 출력
        var showAuthenticationElements = !!profile;
        if (showAuthenticationElements) {
            this.uiElements.profileNameLabel.text(profile.nickname);
            this.uiElements.profileImage.attr('src', profile.picture);
        }
 
        //  프로필 정보 여부에 따라 로그인, 로그아웃, 프로필 버튼을 토글
        this.uiElements.loginButton.toggle(!showAuthenticationElements);
        this.uiElements.logoutButton.toggle(showAuthenticationElements);
        this.uiElements.profileButton.toggle(showAuthenticationElements);
    }, 
    wireEvents: function() {
        var that = this;
 
        //  auth0Lock에서 authenticated 이벤트가 발생할 때 수행할 코드
        this.data.auth0Lock.on('authenticated', function(authResult) {
            console.log(authResult);
 
            //  사용자 정보를 조회
            that.data.auth0Lock.getUserInfo(authResult.accessToken, function (error, profile) {
                if (!error) {
                    //  인증과 사용자 정보 조회에 성공하면 
                    //  auth0에서 발급한 액세스 토큰을 로컬 스토리지에 저장하고, 
                    //  요청 헤더에 새로운 액세스 토큰을 반영
                    //  프로필 정보, 로그인, 로그아웃, 프로필 버튼을 갱신
                    localStorage.setItem('userToken', authResult.accessToken);
                    that.configureAuthenticatedRequests();
                    that.showUserAuthenticationDetails(profile);
                }
            });
        });
        //  Sign in 버튼을 클릭하면, auth0 lock의 show() 메소드를 실행
        this.uiElements.loginButton.click(function(e) {
            //  https://auth0.com/docs/libraries/lock/lock-api-reference#show-
            that.data.auth0Lock.show();
        });
        //  Sign out 버튼을 클릭하면, 
        //  로컬 스토리지에 저장된 액세스 토큰을 삭제
        //  로그인, 로그아웃, 프로필 버튼을 갱신
        this.uiElements.logoutButton.click(function(e) {
            localStorage.removeItem('userToken');
            that.uiElements.logoutButton.hide();
            that.uiElements.profileButton.hide();
            that.uiElements.loginButton.show();
        });
    }
};

 

c:\serverless\24-hour-video\js\main.js

(function() {
    $(document).ready(function() {
        userController.init(configConstants);
    });
}());

 

c:\serverless\24-hour-video\css\main.css

/* 로그아웃 버튼과 프로필 버튼은 최초(시작할 때)에는 보이지 않아야 하므로, diplay: none; 으로 설정 */
 
#auth0-logout {
   display: none;
}
 
#user-profile {
   display: none;
}
 
#profilepicture {
   height: 20px;
   width: 20px;
}