最新消息:XAMPP默认安装之后是很不安全的,我们只需要点击左方菜单的 "安全"选项,按照向导操作即可完成安全设置。

Angular 網站實例 – 記得我篇

XAMPP下载 admin 794浏览 0评论

 Angular 網站實例 – 記得我篇
今天開始 今天完成

上次我們已經成功連上了後端,但是只要使用者ㄧ重新刷瀏覽器,又會回到未登入狀態,今天我們就來讓前端記住登入狀態。

在前端要記住一些資料,我們會用到 cookie ,local storage或者 session storage,至於它們的不同點,可以參考 stackoverflow這篇文章,我們先來做一個有關 local storage 的服務 (service)

公用服務 (utility service)
第一步:造一個 src/apprvices 目錄

mkdir servcies
第二步: 用 angular-cli 產生服務並自動註冊到 app.module.ts

ng generate service utils –module app
第三步:加入 jsonwebtoken 來判斷 token 是否逾期

npm install @auth0/angular-jwt –save
記得使用這個套件,其它套件不能夠跟新的 HttpClientModule 相容

第四步:修改 app.module.ts,導入 JwtModule

// … 省略
import { HttpClientModule } from ‘@angular/commontp’;
import { JwtModule } from ‘@auth0/angular-jwt’;

//… 省略
@NgModule({
//…
imports: [
//…
HttpClientModule,
JwtModule.forRoot({
config: {
tokenGetter: () => {
return localStorage.getItem(‘access_token’);
},
whitelistedDomains: [‘localhost:3000’]
}
})
],
//…
記得同時導入 HttpClientModule 跟 JwtModule

第五步:修改 utils.service.ts

import { Injectable } from ‘@angular/core’;
import { JwtHelperService } from ‘@auth0/angular-jwt’;
export const TOKEN = ‘access_token’;
@Injectable()
export class UtilsService {
constructor(
private jwtHelper: JwtHelperService
) { }

isTokenExpired(token: string = TOKEN): boolean {
let jwtStr = this.getToken(token);
if (jwtStr) {
return this.jwtHelper.isTokenExpired(jwtStr);  // token expired?
} else {
return true;        // no token
}
}

writeToken(value: string, token: string = TOKEN) {
localStorage.setItem(token, value);
}

getToken(token: string = TOKEN) {
return localStorage.getItem(token);
}

removeToken(token: string = TOKEN) {
if (this.getToken(token)) {
localStorage.removeItem(token);
}
}
}
預設的 token 的關鍵(key) 為 access_token,為了可以寫入不同的關鍵,我們參數保留了 token 這個關鍵。
第六步: 將 index.ts 加入 src/apprvices

export * from ‘./utils.servcie’;
修改使用者服務
第一步:導入公用服務

// … 省略
import { UtilsService } from ‘../..rvices’;

@Injectable()
export class UserService {
loginStatus = new BehaviorSubject<boolean>(false);
currentUser = new BehaviorSubject<User>(null);
constructor(
private http: HttpClient,
private appConfig: AppConfig,
private utils: UtilsService
) { }
// … 省略
第二步:修改 login() 程式,後端驗證成功會傳回關鍵值 (value),如果使用者有勾選 記得我,我們用公用服務將它寫入 localstorage

// … 省略
login(loginData): Observable<boolean> {
return this.loginServer(loginData)
.map((res: Response) => {
if (res.success) {
this.loginStatus.next(true);
this.currentUser.next(loginData.username);
if (loginData.rememberMe) {
this.utils.writeToken(res.payload);
}
return true;
} else {
return false;
}
},
//… 省略
第三步:修改 logout(),登出時將 token 清掉

logout() {
this.loginStatus.next(false);
this.currentUser.next(null);
this.utils.removeToken();
}
第四步:加入 checkuser() 函數

// when startup
checkUser(): Observable<boolean> {
if (!this.utils.isTokenExpired()) {
this.loginStatus.next(true);
return of(true);
} else {
console.log(‘no token or token is expired’);
this.utils.removeToken();
return of(false);
}
}
這個函數馬上會用到,基本上是先檢查 token 有沒有過期,沒有的話將 loginStatus 設為真

第五步:確認
做登入後檢查是否 localstorage 已經寫入,正常狀態如截圖

QQ截图20181009165056
 啟動服務 (startup service)
接下來我們要在瀏覽器重新啟動時來檢查這個 token,我們先來做一個服務
第一步:產生 startup.servcie.ts 在 src/apprvices 下

ng generate servcie startup –module app
第二步:修改程式

import { Injectable, Injector } from ‘@angular/core’;
import { Router } from ‘@angular/router’;
import { UtilsService } from ‘.’;
import { UserService } from ‘../userrvice/user.service’;
@Injectable()
export class StartupService {
constructor(
private injector: Injector,
private utils: UtilsService,
private userService: UserService
) { }
load(): Promise<any> {
return new Promise((resolve, reject) => {
return this.userService.checkUser()
.subscribe(res => {
if (res) {
setInterval(() => {
this.checkStatus();
}, 1000 * 60 * 5)    // check current status every 5 min
}
resolve(res);
}, err => {
console.log(err);
reject(err);
});
});
}
checkStatus() {
if (this.utils.isTokenExpired()) {   // if token expired
this.userService.logout();
const router = this.injector.get(Router);
router.navigate([‘/’]);
console.log(‘logout due to token expired’);
}
}
}
startup 服務一定要建置一個 Promise 函數回給系統,這裡我們用 load()
在 load() 函數中利用使用者服務的 checkuser() 函數,如果 token 還沒過期,使用者服務的 loginStatus 會變成 true
每五分鐘檢查一下狀態 checkStatus(),如果逾期,做一個 logout() 的動作然後將頁面導回首頁
因為在 Startup 時無法直接用 DI (Depency Injection) Router,請參考 stackoverflow,我們需要用到Injector 來導入Router
第三步: 修改app.module.ts

//… 省略
import { NgModule, APP_INITIALIZER, Injector } from ‘@angular/core’;
//… 省略
export function startupServiceFactory(startupService: StartupService): Function { return () => startupService.load(); }
// … 省略
@NgModule({
// …
providers: [
UtilsService,
StartupService,
{
provide: APP_INITIALIZER,
useFactory: startupServiceFactory,
deps: [StartupService, Injector],
multi: true
}
],
//… 省略
好了,現在當您登入系統,回到首頁,重新刷瀏覽器,應該會留在登入狀態(瀏覽列底色),但是看不到使用者名稱,也沒辦法登出,我們下次來解決這個問題。

转载请注明:XAMPP中文组官网 » Angular 網站實例 – 記得我篇

您必须 登录 才能发表评论!