MEAN Stack Front to Back (MEANAuthApp)

Slides:



Advertisements
Similar presentations
- SW_Desing Study Group -
Advertisements

Spring MVC ㅇ 스프링 MVC 구성요소 설명 DispatcherServlet 클라이언트의 요청을 컨트롤러에게 전달하고
컴퓨터 응용 및 실습 Part1. OOP&Java Programming data type Review
패스포트로 사용자 인증하기 9장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
AJAX 기본중의 기본 xmlhttprequest
IoT(사물인터넷) 보안 2016년 2학기 3. 라즈베리파이와 node.js.
개발자에게 SharePoint Services 란 무엇인가?
12장. JSP에서 자바빈 활용 제12장.
웹어플리케이션 보안 Web application security
채팅 서버 만들기 10장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
J2ME(Java 2 Micro Edition) 무선 장치용 UI의 핵심 컴포넌트
모바일 서버 만들기 13장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
2 서블릿의 기초.
Web Server와 DB 연동.
소프트웨어공학 UML 학기.
4 쿠키와 세션.
XXXX SSO 구축 SSO (Single Sign-On) -사용자 인증 및 권한부여 통합 관리 시스템
웹 서버 만들기 5장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
데이터베이스 사용하기 6장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
2장. UML 기본 개념.
고수준 사용자 인터페이스 프로그래밍 Lecture #4.
MEAN Stack Front to Back (MEANAuthApp)
MEAN Stack Front to Back
AJAX 커머스아이 박준열.
윤성우의 열혈 C++ 프로그래밍 윤성우 저 열혈강의 C++ 프로그래밍 개정판 Chapter 03. 클래스의 기본.
JSON-RPC 서버 만들기 11장 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안 2017/03
소프트웨어설계 UML 학기.
Chapter 05. 클래스 완성. chapter 05. 클래스 완성 01. 복사 생성자 복사 생성(Copy Construction) 생성될 때 자신과 같은 타입의 객체를 변수로 받아, 이 객체와 같은 값을 갖는 새로운 객체를 생성하는 것 명시적인 생성 과정뿐만.
MEAN Stack Front to Back (MEANAuthApp)
DataScience Lab. 박사과정 김희찬 (월)
ASP.NET Mobile Controls
웹 어플리케이션 보안 2016년 2학기 8. MEAN APP – USER CRM.
DataStage 운영자 지침서 Operator’s Guide
MEAN Stack Front to Back (MEANAuthApp)
8 데이터베이스 사용하기.
12 데이터베이스 사용하기.
주소록 프로그램.
Web Socket.
장애인복지 정책.
강남 DataBinding 스타일 Windows 8 앱개발자라면 꼭 알아야할 개발자가 알아야할 Binding.
암호학 응용 Applied cryptography
Cairngorm(캔곰) : Flex UI 프레임워크
웹 어플리케이션 보안 2016년 2학기 2. Node routing.
JavaScript COOKIE Chapter 10 Part III
Web Vulnerabilities 정보 보호 2008/05/31 Getroot.
IOS Press
Ch.1 Iterator Pattern <<interface>> Aggregate +iterator
MEAN Stack Front to Back
SNS 로그인 API 연동 조휘제.
MEAN Stack Front to Back (MEANAuthApp)
상품등록 방식 비교 년 4월 23일 (주)에이치케이넷츠.
제 2장 어휘구조와 자료형 토 큰 리 터 럴 주 석 자 료 형 배 열 형.
MEAN Stack Front to Back (MEANAuthApp)
MEAN Stack Front to Back (MEANAuthApp)
SpringFramework 중간고사 요약 REST by SpringFramework.
MEAN Stack Front to Back (MEANAuthApp)
노드로 만들 수 있는 대표적인 서버와 용도 준비마당 Do it! Node.js 프로그래밍 이지스퍼블리싱 제공 강의 교안
Java 3장. 자바의 기본 구조 I : 변수, 자료형, 연산자 public class SumTest {
LOGIN할 때 아이디, 비번 입력 여부 체크하기
Spring Security 2015 Web Service Computing.
MEAN Stack Front to Back (MEANAuthApp)
JSP 빈즈 1.JSP 빈즈? JSP와 연동을 위해 만들어진 컴포넌트 클래스를 말한다. JSP 빈즈는 컨테이너에 위치하며, 데이터 처리와 공용화된 기능을 제공하기 때문에 빈즈를 잘 활용하면 프로그램의 중복을 줄이고 좀더 원할한 유지보수가 가능한다. 물론 , 모든 JSP를.
웹어플리케이션보안 난수화 토큰인증 중부대학교 정보보호학과 이병천 교수.
Node Red 컴퓨터공학과 오동근 1.
Java의 정석 제 7 장 객체지향개념 II-3 Java 정석 남궁성 강의
JavaScript의 오브젝트 JavaScript Objects.
발 표 자 : 7조 손 창 국 윤 오 성, 박 진 완 객체 지향 프로그래밍 C++
MEAN Stack Front to Back
MEAN Stack Front to Back (MEANAuthApp)
MEAN Stack Front to Back (MEANAuthApp)
Presentation transcript:

MEAN Stack Front to Back (MEANAuthApp) 8. Login & Logout 9. Protected Requests & Auth Guard

목차 1. 환경 구축 2. Express Setup & Routes 3. User Model and Register 4. API authentication and Token 5. Angular 4 Components & Routes 6. Register Component, Validation & Flash messages 7. Auth Service & User Registration 8. Login & Logout 9. Protected Requests & Auth Guard 10. App Deployment to Heroku

8. Login & Logout

로그인 기능 추가 Login.component.html 에 로그인 폼 작성 Login 버튼 클릭시 <h2 class="page-header">Login </h2> <form (submit)="onLoginSubmit()">   <div class="form-group">     <label>Username</label>     <input type="text" class="form-control" [(ngModel)]="username" name="username">   </div>     <label>Password</label>     <input type="password" class="form-control" [(ngModel)]="password" name="password">   <input type="submit" class="btn btn-primary" value="Login"> </form> Login 버튼 클릭시 onLoginSubmit() 함수 실행 Username, password 값에 대해 2-way databinding 설정

Login.component.ts 파일 수정 import { Component, OnInit } from '@angular/core'; import { AuthService } from '../../services/auth.service'; import { Router } from '@angular/router'; import { FlashMessagesService } from 'angular2-flash-messages';   @Component({   selector: 'app-login',   templateUrl: './login.component.html',   styleUrls: ['./login.component.css'] }) export class LoginComponent implements OnInit {   username: string;   password: string;   constructor(     private authService: AuthService,     private router: Router,     private flashMessage: FlashMessagesService   ) { }   ngOnInit() {   }   onLoginSubmit(){     const user = {       username: this.username,       password: this.password     }     this.authService.authenticateUser(user).subscribe(data => {       console.log(data);     }); } Login.component.ts 파일 수정 필요한 서비스 import 로그인에 필요한 변수 선언 Constructor에 서비스 등록 사용자 입력 값을 user 변수에 저장 Auth.service.ts에 authenticateUser() 함수 추가 예정 Subscribe 메서드로 옵저버 등록 테스트 서버에서 보내주는 data를 확인

로그인 기능 추가 auth.service.ts Auth.service에 authenticateUser 함수 선언 registerUser(user){   let headers = new Headers();   headers.append('Content-Type', 'application/json');   return this.http.post('http://localhost:3000/users/register', user, {headers: headers})     .map(res => res.json()); }   authenticateUser(user){   return this.http.post('http://localhost:3000/users/authenticate', user, {headers: headers}) Auth.service에 authenticateUser 함수 선언 - user 데이터를 'http://localhost:3000/users/authenticate’에 전송하고 응답을 받아옴

테스트 미등록된 사용자이름 패스워드 틀림 로그인 성공시 토큰과 사용자 정보 전송

authenticateUser 함수 Login.component.ts 파일의 authenticateUser 함수 작성 this.authService.authenticateUser(user).subscribe(data => {   if(data.success) {     this.authService.storeUserData(data.token, data.user);     this.flashMessage.show('You are now logged in', {cssClass: 'alert-success', timeout: 5000});     this.router.navigate(['dashboard']);   } else {     this.flashMessage.show(data.msg, {cssClass: 'alert-danger', timeout: 5000});     this.router.navigate(['login']);   } }); 로그인 성공시 - 토큰과 user 데이터를 로컬스토리지에 저장 (auth.service.ts에 storeUserData함수 작성 예정) - 로그인 성공 flashMessage 표시 - dashboard 페이지로 리다이렉트 로그인 실패시 - 로그인 실패 flashMessage 표시 - login 페이지로 리다이렉트

storeUserData 함수 Auth.service.ts 에 storeUserData 함수 선언 localStorage 에는 authenticateUser(user){   let headers = new Headers();   headers.append('Content-Type', 'application/json');   return this.http.post('http://localhost:3000/users/authenticate', user, {headers: headers})     .map(res => res.json()); }   storeUserData(token, user){   localStorage.setItem('id_token', token);   localStorage.setItem('user', JSON.stringify(user));   this.authToken = token;   this.user = user; localStorage 에는 string 형식으로 저장 token, user 데이터를 localStorage에 저장 token, user 데이터를 this.authToken, this.user 변수로 저장 (앱 내부에서 로그인 여부 확인을 위한 변수)

테스트 로그인 성공시 Dashboard 로 이동 localStorage에 토큰과 사용자정보 저장

로그아웃 기능 추가 Auth.service.ts 에 logout 함수 추가 로그인 변수의 값을 지우고 로컬스토리지를 비움 storeUserData(token, user){   localStorage.setItem('id_token', token);   localStorage.setItem('user', JSON.stringify(user));   this.authToken = token;   this.user = user; }   logout(){   this.authToken = null;   this.user = null;   localStorage.clear(); 로그인 변수의 값을 지우고 로컬스토리지를 비움

로그아웃 기능 추가 UI에 Logout 버튼 추가 Navbar.component.html 파일 수정 <ul class="nav navbar-nav navbar-right">   <li [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}"><a [routerLinkActive]="['active']" [routerLink]="['/login']">Login</a></li>   <li [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}"><a [routerLinkActive]="['active']" [routerLink]="['/register']">Register</a></li>   <li><a (click)="onLogoutClick()" href="#">Logout</a></li> </ul> 메뉴에 Logout 버튼 추가 클릭하면 onLogoutClick() 함수 실행 Navbar.component.ts에 onLogoutClick() 함수 작성 예정

로그아웃 기능 추가 Navbar.component.ts 파일에 onLogoutClick() 함수 추가 import { Component, OnInit } from '@angular/core'; import { AuthService } from '../../services/auth.service'; import { Router } from '@angular/router'; import { FlashMessagesService } from 'angular2-flash-messages';   @Component({   selector: 'app-navbar',   templateUrl: './navbar.component.html',   styleUrls: ['./navbar.component.css'] }) export class NavbarComponent implements OnInit {   constructor(     private authService: AuthService,     private router: Router,     private flashMessage: FlashMessagesService   ) { }   ngOnInit() {   }   onLogoutClick(){     this.authService.logout();     this.flashMessage.show('You are logged out', {       cssClass: 'alert-success',       timeout: 3000     });     this.router.navigate(['/login']);     return false; } 이를 위해서는 authService, router, flashmessage 등의 서비스가 필요 Constructor에 서비스 등록 authService의 logout()함수 실행 로그아웃 flashMessage 표시 login 페이지로 리다이렉트 (router 서비스 이용)

로그아웃 테스트 login 페이지로 리다이렉트 localStorage의 토큰 정보가 삭제됨

9. Protected Requests & Auth Guard

Protected Request 페이지 요청에 대한 토큰인증 어떻게 설정하나? 로그인된 상태에서 토큰을 제시해야만 접근 가능한 페이지 설정 Dashboard 페이지는 로그인 상태에서만 접속 가능 Profile 페이지에는 토큰을 제시해야만 접근 허용 (서버에서 토큰 검증) 서버측 http://localhost:3000/users/profile 페이지에는 이미 토 큰 인증이 설정되어 있음 어떻게 설정하나? 로그인되면 토큰을 받음 Profile 페이지 요청시 토큰을 첨부하도록 수정

토큰인증 서비스 설정 Auth.service.ts 파일에서 getProfile() 함수에 토큰인증 서비스 추가   let headers = new Headers();   this.loadToken();   headers.append('Authorization', this.authToken);   headers.append('Content-Type', 'application/json');   return this.http.get('http://localhost:3000/users/profile', {headers: headers})     .map(res => res.json()); }   storeUserData(token, user){   localStorage.setItem('id_token', token);   localStorage.setItem('user', JSON.stringify(user));   this.authToken = token;   this.user = user; loadToken(){   const token = localStorage.getItem('id_token'); Profile 페이지 접근을 위한 토큰인증 서비스 작성 토큰을 읽어와서authorization 헤더에 첨부 http.get 요청을 보내고 응답을 받아옴 localStorage에서 토큰을 읽어와서 this.authToken에 로드하는 함수

토큰인증 서비스를 profile.component에 적용 import { Component, OnInit } from '@angular/core'; import { AuthService } from '../../services/auth.service'; import { Router } from '@angular/router';   @Component({   selector: 'app-profile',   templateUrl: './profile.component.html',   styleUrls: ['./profile.component.css'] }) export class ProfileComponent implements OnInit {   user: Object;   constructor(     private authService: AuthService,     private router: Router   ) { }   ngOnInit() {     this.authService.getProfile().subscribe(profile => {         this.user = profile.user;       },       err => {         console.log(err);         return false;     });   }  } AuthService, Router 서비스 import AuthService, Router 서비스 등록 Profile 페이지를 열 때 authService.getProfile 서비스 적용 Subscribe 메서드로 observer 등록 서버에서 제공하는 사용자 정보를 적용

Profile 페이지 작성 Profile.component.html 페이지 로그인된 경우에만 사용자 정보를 표시 사용자 정보 user 가 존재하는 경우에만 div 영역을 생성 <div *ngIf="user">   <h2 class="page-header">{{user.name}}</h2>   <ul class="list-group">     <li class="list-group-item">Username: {{user.username}}</li>     <li class="list-group-item">Email: {{user.email}}</li>   </ul> </div>

테스트 로그인 된 상태에서만 profile 페이지 접근 가능

패키지 버전 관리 (임시) JWT 인증 관련 최신버전에서 에러 발생 서버측 패키지를 이전 버전으로 관리 Package.json 파일에서 버전을 다음과 같이 수정 node_modules 폴더 삭제 > npm install 다시 실행 (수정된 버전으로 설치됨) "jsonwebtoken": "^7.4.1", "passport": "^0.3.2", "passport-jwt": "^2.2.1"

패키지 버전 관리 (임시) 버전업시 수정했던 것 원위치 Auth.service.ts 에서 토큰 이름 지정 서버측 route/users.js 수정 Jwt 토큰 생성시 json객체 형식의 데이터 입력 const token = jwt.sign({data: user}, config.secret, {  const token = jwt.sign(user, config.secret, { Auth.service.ts 에서 토큰 이름 지정 loggedIn(){ // return tokenNotExpired(); return tokenNotExpired('id_token'); }

로그인 여부에 따른 메뉴 표시 재조정 로그인된 경우 표시될 페이지 로그아웃된 경우 표시될 페이지 Home (항상 표시) Dashboard (추가) Profile (추가) Logout 로그아웃된 경우 표시될 페이지 Login Register 로그인/로그아웃 상태를 판단할 수 있는 기능 필요 토큰은 유효기간이 있어서 기간이 지나면 유효하지 않음 토큰이 유효한지 여부를 확인 필요

Angular2-jwt 패키지 이용 Angular2-jwt https://github.com/auth0/angular2-jwt > npm install angular2-jwt

Angular2-jwt 패키지 이용 angular2-jwt 설치 (frontend에 설치) > cd meanauthapp/angular-src > npm install angular2-jwt --save meanauthapp/angular-src/package.json 에 설치 확인 Auth.service.ts에 tokenNotExpired, loggedIn() 등록 import { Injectable } from '@angular/core'; import { Http, Headers } from '@angular/http'; import 'rxjs/add/operator/map'; import { tokenNotExpired } from 'angular2-jwt';   중략 loadToken(){   const token = localStorage.getItem('id_token');   this.authToken = token; } loggedIn(){   return tokenNotExpired(); 토큰이 유효한지 여부를 확인하는 기능

Navbar.component.html 파일에 적용 로그인 되어 있으면 항목 표시 *ngIf="authService.loggedIn()“ 로그인 안된 경우 항목 표시 *ngIf=“!authService.loggedIn()" <ul class="nav navbar-nav navbar-right">   <li *ngIf="authService.loggedIn()" [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}"><a [routerLinkActive]="['active']" [routerLink]="['/dashboard']">Dashboard</a></li>   <li *ngIf="authService.loggedIn()" [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}"><a [routerLinkActive]="['active']" [routerLink]="['/profile']">Profile</a></li>   <li *ngIf="!authService.loggedIn()" [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}"><a [routerLinkActive]="['active']" [routerLink]="['/login']">Login</a></li>   <li *ngIf="!authService.loggedIn()" [routerLinkActive]="['active']" [routerLinkActiveOptions]="{exact:true}"><a [routerLinkActive]="['active']" [routerLink]="['/register']">Register</a></li>   <li *ngIf="authService.loggedIn()"><a (click)="onLogoutClick()" >Logout</a></li> </ul>

로그인 안된 경우 접근 금지 설정 AuthGuard 서비스 설정 별도의 폴더 app/guards 생성 auth.guard.ts 생성 import { Injectable } from '@angular/core'; import { Router, CanActivate } from '@angular/router'; import { AuthService } from '../services/auth.service'; @Injectable() export class AuthGuard implements CanActivate { constructor(private authService: AuthService, private router: Router) { } canActivate(){ if(this.authService.loggedIn()){ return true; } else { this.router.navigate(['/login']); return false; 로그인 되어 있으면 canActivate가 true 리턴 로그인 안되어 있으면 로그인 페이지로 리다이렉트하고 canActivate가 false 리턴

App.module.ts에 auth.guard 적용 import { ValidateService } from './services/validate.service'; import { AuthService } from './services/auth.service'; import { FlashMessagesModule } from 'angular2-flash-messages'; import { AuthGuard } from './guards/auth.guard';   const appRoutes: Routes = [   {path:'', component: HomeComponent},   {path:'register', component: RegisterComponent},   {path:'login', component: LoginComponent},   {path:'dashboard', component: DashboardComponent, canActivate:[AuthGuard]},   {path:'profile', component: ProfileComponent, canActivate:[AuthGuard]} ] 중략…   providers: [ValidateService, AuthService, AuthGuard], dashboard와 profile 컴포넌트에 AuthGuard 적용

최종 사이트 테스트 (경) 성공! (축) 로그인시 메뉴 로그아웃시 메뉴 토큰인증 설정된 profile 페이지 접속 성공

서비스 빌드 (컴파일) 개발환경: 현재까지는 angular live server 환경에서 개발 http://localhost:3000/ 백엔드 서버 http://localhost:4200/ 클라이언트 개발을 위한 라이브 서버 배포환경: 개발 완료 후 메인 서버로 통합 운영 http://localhost:3000/ 공용 서버로 이전 준비 서버명, 포트번호 고려 http://isweb.joongbu.ac.kr:portnumber/

준비사항 Auth.service.ts 파일 수정 서버명칭, 포트번호 설정을 쉽게 하기 위한 준비 Full path 지정 @Injectable() export class AuthService { authToken: any; user: any; constructor(private http:Http) { } registerUser(user){ let headers = new Headers(); headers.append('Content-Type','application/json'); let ep = this.prepEndpoint('users/register'); return this.http.post(ep, user,{headers: headers}) .map(res => res.json()); } 중략…. prepEndpoint(ep){ return 'http://localhost:3000/'+ep; // return 'http://isweb.joongbu.ac.kr:3000/'+ep; Auth.service.ts 파일 수정 서버명칭, 포트번호 설정을 쉽게 하기 위한 준비 Full path 지정 공용서버로 옮기는 경우의 변경

준비사항 Auth.service.ts 파일 수정 다른 함수들도 패스 수정 authenticateUser(user){ let headers = new Headers(); headers.append('Content-Type','application/json'); let ep = this.prepEndpoint('users/authenticate'); return this.http.post(ep, user,{headers: headers}) .map(res => res.json()); } getProfile(){ this.loadToken(); headers.append('Authorization', this.authToken); let ep = this.prepEndpoint('users/profile'); return this.http.get(ep,{headers: headers})

서비스 빌드 (컴파일) 빌드 명령어 빌드를 수행하면 public 폴더에 클라이언트측 콘텐츠가 배포되며 서버코드와 직접 연동됨 > cd angular-src > ng build 빌드를 수행하면 public 폴더에 클라이언트측 콘텐츠가 배포되며 서버코드와 직접 연동됨 백엔드 서버 포트(3000)로 직접 연결 모든 서비스 동작

공용 서버로 업로드 Auth.service.ts 파일에서 필요사항 수정 후 빌드 서버에 업로드 및 서비스 실행 자신에게 할당된 포트번호 사용 서버에 업로드 및 서비스 실행 서버에 전체 프로젝트 폴더 업로드 필요시 서버 파일명 수정 > node app.js & 웹브라우저로 접속 테스트 http://isweb.joongbu.ac.kr:포트번호/ 로 접속 prepEndpoint(ep){ // return 'http://localhost:3000/'+ep; return 'http://isweb.joongbu.ac.kr:3000/'+ep; }

과제 3. meanauthapp 서버에서 실행하기 지금까지 완성된 프로젝트를 isweb 서버의 자신의 계정 에 업로드, 실행하고 자신의 홈페이지 과제물 페이지에 링크하기 중간고사 실무과제에 포함