使用 Amazon Cognito 对 Angular 应用程序进行身份验证
介绍
先决条件
入门
结论
介绍
本文将使用最新版本的 Angular 创建一个应用程序,并使用 Amazon Cognito 服务进行身份验证。Amazon Cognito 服务提供了一个简单安全的集成,支持在 WEB 或移动应用程序中进行用户登录、注册和控制。
先决条件
开始之前,您需要安装并配置以下工具来创建 Angular 应用程序。
- git:Git 是一个分布式版本控制系统,它将用于同步存储库。
- Node.js 和 npm:Node.js 是一个基于 Google V8 引擎的 JavaScript 代码运行时软件。npm 是 Node.js 的包管理器(Node.js Package Manager)。我们将使用它们来构建和运行 Angular 应用程序,并安装所需的库。
- Angular CLI:Angular CLI 是一个用于 Angular 的命令行实用工具,它将用于创建 Angular 应用程序的基本结构。
- IDE(例如Visual Studio Code或WebStorm):IDE(集成开发环境)是一种带有图形界面的工具,可以帮助开发应用程序,它将用于开发 Angular 应用程序。
入门
在 Amazon Cognito 上创建和配置帐户
Amazon Cognito是一种简单安全的身份验证服务,支持用户在 WEB 或移动应用程序中登录、注册和控制。
1.让我们创建账户。访问网站https://aws.amazon.com/cognito/并点击“立即注册”按钮。
2.点击“创建新的 AWS 账户”按钮。
3.填写电子邮件地址、密码、确认密码、AWS 账户名称、安全检查等字段,然后点击“继续”按钮(第 1 步,共 5 步)。
4.点击“个人 - 您自己的项目”选项,填写“全名”、“电话号码”、“国家/地区”、“地址”、“城市”、“州/省/地区”、“邮政编码”等字段,勾选“我已阅读并同意 AWS 客户协议的条款”复选框,然后点击“继续”按钮(第 2 步,共 5 步)。
5.填写信用卡号、到期日、持卡人姓名等字段,点击“使用我的联系地址”选项,填写CPF 号码、税务登记号、出生日期、邮政编码、居住地、税务地址等字段,然后点击“验证并继续”按钮(步骤 3,共 5 步)。
笔记:
- 某些字段可能因国家/地区而异。
6.点击“短信 (SMS)”选项,在“国家或地区代码”字段中选择一个选项,填写“手机号码”字段,输入如上所示的字符,然后点击“发送短信”按钮(步骤 4/5)。
7.填写验证码字段,然后点击“继续”按钮(第 4 步,共 5 步)。
8.点击“基本支持 - 免费”选项,然后点击“完成注册”按钮。
9.点击“转到 AWS 管理控制台”按钮。
10.点击“Root 用户”选项,填写“Root 用户电子邮件地址”字段,然后点击“下一步”按钮。
11.填写安全检查字段,然后点击提交按钮。
12.在“密码”字段中填写信息,然后点击“登录”按钮。
13.点击“切换到新的主机主页”按钮。
14.点击菜单“安全、身份与合规”,然后点击子菜单“Cognito”。
15.点击链接“试用新界面”。
16.点击“创建用户池”按钮。
17.点击“电子邮件”选项,然后点击“下一步”按钮。
18.点击“Cognito 默认设置”、“无 MFA”、“启用自助帐户恢复 - 推荐”、“仅限电子邮件”选项,然后点击“下一步”按钮。
19.点击“启用自助注册”、“允许 Cognito 自动发送消息以进行验证和确认 - 推荐”、“发送电子邮件”、“验证电子邮件地址”等选项,然后点击“下一步”按钮。
20.点击“使用 Cognito 发送电子邮件”选项,然后点击“下一步”按钮。
21.填写“用户池名称”字段,点击“公共客户端”选项,填写“应用程序客户端名称”字段,点击“不生成客户端密钥”选项,然后点击“登录”按钮。
22.点击“创建用户池”按钮。
23.点击带有用户池名称的angular-cognito链接。
24.复制显示的用户池 ID,在我的例子中,us-east-2_pptCj2gqV显示该 ID 是因为该 ID 将在 Angular 应用程序中进行配置,然后单击链接App integration。
25.1452opnjll0ldmocs201b1oimu复制显示的客户端 ID,在我的例子中,之所以显示ID,是因为该 ID 将在 Angular 应用程序中进行配置。
26.完成!账户已创建,用户池 ID 和客户端 ID 已生成。
创建 Angular 应用程序
Angular是一个用于构建 Web、移动和桌面应用程序的开发平台,它使用 HTML、CSS 和 TypeScript(JavaScript)。目前,Angular 的版本为 14,Google 是该项目的主要维护者。
1.@angular/cli让我们使用路由文件和 SCSS 样式格式,以 Angular 基本结构创建应用程序。
ng new angular-cognito --routing true --style scss
CREATE angular-cognito/README.md (1060 bytes)
CREATE angular-cognito/.editorconfig (274 bytes)
CREATE angular-cognito/.gitignore (548 bytes)
CREATE angular-cognito/angular.json (3261 bytes)
CREATE angular-cognito/package.json (1079 bytes)
CREATE angular-cognito/tsconfig.json (863 bytes)
CREATE angular-cognito/.browserslistrc (600 bytes)
CREATE angular-cognito/karma.conf.js (1432 bytes)
CREATE angular-cognito/tsconfig.app.json (287 bytes)
CREATE angular-cognito/tsconfig.spec.json (333 bytes)
CREATE angular-cognito/.vscode/extensions.json (130 bytes)
CREATE angular-cognito/.vscode/launch.json (474 bytes)
CREATE angular-cognito/.vscode/tasks.json (938 bytes)
CREATE angular-cognito/src/favicon.ico (948 bytes)
CREATE angular-cognito/src/index.html (300 bytes)
CREATE angular-cognito/src/main.ts (372 bytes)
CREATE angular-cognito/src/polyfills.ts (2338 bytes)
CREATE angular-cognito/src/styles.scss (80 bytes)
CREATE angular-cognito/src/test.ts (745 bytes)
CREATE angular-cognito/src/assets/.gitkeep (0 bytes)
CREATE angular-cognito/src/environments/environment.prod.ts (51 bytes)
CREATE angular-cognito/src/environments/environment.ts (658 bytes)
CREATE angular-cognito/src/app/app-routing.module.ts (245 bytes)
CREATE angular-cognito/src/app/app.module.ts (393 bytes)
CREATE angular-cognito/src/app/app.component.scss (0 bytes)
CREATE angular-cognito/src/app/app.component.html (23364 bytes)
CREATE angular-cognito/src/app/app.component.spec.ts (1100 bytes)
CREATE angular-cognito/src/app/app.component.ts (220 bytes)
✔ Packages installed successfully.
Successfully initialized git.
2.安装并配置 Bootstrap CSS 框架。按照文章“将 Bootstrap CSS 框架添加到 Angular 应用程序”中的步骤 2 和 3 进行操作。
3.在以下文件中配置cognito.userPoolIdAmazon Cognito 用户池 ID变量和cognito.userPoolWebClientIdAmazon Cognito WEB 客户端 ID变量。src/environments/environment.tssrc/environments/environment.prod.ts
cognito: {
userPoolId: 'us-east-2_pptCj2gqV',
userPoolWebClientId: '1452opnjll0ldmocs201b1oimu',
},
4.安装aws-amplify库。
npm install aws-amplify
5.修改src/polyfills.ts文件。添加如下所示的全局声明。从 Angular 版本 6 开始,此配置是必需的。
(window as any).global = window;
6.创建CognitoService服务。
ng generate service cognito --skip-tests=true
CREATE src/app/cognito.service.ts (136 bytes)
7.修改src/app/cognito.service.ts文件并添加如下代码行。
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import Amplify, { Auth } from 'aws-amplify';
import { environment } from '../environments/environment';
export interface IUser {
email: string;
password: string;
showPassword: boolean;
code: string;
name: string;
}
@Injectable({
providedIn: 'root',
})
export class CognitoService {
private authenticationSubject: BehaviorSubject<any>;
constructor() {
Amplify.configure({
Auth: environment.cognito,
});
this.authenticationSubject = new BehaviorSubject<boolean>(false);
}
public signUp(user: IUser): Promise<any> {
return Auth.signUp({
username: user.email,
password: user.password,
});
}
public confirmSignUp(user: IUser): Promise<any> {
return Auth.confirmSignUp(user.email, user.code);
}
public signIn(user: IUser): Promise<any> {
return Auth.signIn(user.email, user.password)
.then(() => {
this.authenticationSubject.next(true);
});
}
public signOut(): Promise<any> {
return Auth.signOut()
.then(() => {
this.authenticationSubject.next(false);
});
}
public isAuthenticated(): Promise<boolean> {
if (this.authenticationSubject.value) {
return Promise.resolve(true);
} else {
return this.getUser()
.then((user: any) => {
if (user) {
return true;
} else {
return false;
}
}).catch(() => {
return false;
});
}
}
public getUser(): Promise<any> {
return Auth.currentUserInfo();
}
public updateUser(user: IUser): Promise<any> {
return Auth.currentUserPoolUser()
.then((cognitoUser: any) => {
return Auth.updateUserAttributes(cognitoUser, user);
});
}
}
8.创建SignUpComponent组件。
ng generate component sign-up --skip-tests=true
CREATE src/app/sign-up/sign-up.component.scss (0 bytes)
CREATE src/app/sign-up/sign-up.component.html (22 bytes)
CREATE src/app/sign-up/sign-up.component.ts (279 bytes)
UPDATE src/app/app.module.ts (638 bytes)
9.修改src/app/sign-up/sign-up.component.ts文件。导入Router服务CognitoService和创建signUp方法,confirmSignUp如下所示。
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { IUser, CognitoService } from '../cognito.service';
@Component({
selector: 'app-sign-up',
templateUrl: './sign-up.component.html',
styleUrls: ['./sign-up.component.scss'],
})
export class SignUpComponent {
loading: boolean;
isConfirm: boolean;
user: IUser;
constructor(private router: Router,
private cognitoService: CognitoService) {
this.loading = false;
this.isConfirm = false;
this.user = {} as IUser;
}
public signUp(): void {
this.loading = true;
this.cognitoService.signUp(this.user)
.then(() => {
this.loading = false;
this.isConfirm = true;
}).catch(() => {
this.loading = false;
});
}
public confirmSignUp(): void {
this.loading = true;
this.cognitoService.confirmSignUp(this.user)
.then(() => {
this.router.navigate(['/signIn']);
}).catch(() => {
this.loading = false;
});
}
}
10.修改src/app/sign-up/sign-up.component.html文件。添加如下代码行。
<div class="row justify-content-center my-5">
<div class="col-4">
<div class="card">
<div class="card-body" *ngIf="!isConfirm">
<div class="row">
<div class="col mb-2">
<label for="email" class="form-label">Email:</label>
<input type="email" id="email" name="email" #email="ngModel" [(ngModel)]="user.email" class="form-control form-control-sm">
</div>
</div>
<div class="row">
<div class="col mb-2">
<label for="password" class="form-label">Password:</label>
<div class="input-group input-group-sm">
<input [type]="user.showPassword ? 'text' : 'password'" id="password" name="password" #password="ngModel" [(ngModel)]="user.password" class="form-control form-control-sm">
<button type="button" class="btn btn-outline-secondary" (click)="user.showPassword = !user.showPassword">
<i class="bi" [ngClass]="{'bi-eye-fill': !user.showPassword, 'bi-eye-slash-fill': user.showPassword}"></i>
</button>
</div>
</div>
</div>
<div class="row">
<div class="col d-grid">
<button type="button" (click)="signUp()" class="btn btn-sm btn-success" [disabled]="loading">
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" *ngIf="loading"></span>
Sign up
</button>
</div>
</div>
</div>
<div class="card-body" *ngIf="isConfirm">
<div class="row">
<div class="col mb-2">
<label for="code" class="form-label">Code:</label>
<input type="text" id="code" name="code" #code="ngModel" [(ngModel)]="user.code" class="form-control form-control-sm">
</div>
</div>
<div class="row">
<div class="col d-grid">
<button type="button" (click)="confirmSignUp()" class="btn btn-sm btn-success" [disabled]="loading">
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" *ngIf="loading"></span>
Confirm
</button>
</div>
</div>
</div>
</div>
</div>
</div>
11.创建SignInComponent组件。
ng generate component sign-in --skip-tests=true
CREATE src/app/sign-in/sign-in.component.scss (0 bytes)
CREATE src/app/sign-in/sign-in.component.html (22 bytes)
CREATE src/app/sign-in/sign-in.component.ts (279 bytes)
UPDATE src/app/app.module.ts (490 bytes)
12.修改src/app/sign-in/sign-in.component.ts文件。导入Router服务CognitoService并创建signIn如下方法。
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { IUser, CognitoService } from '../cognito.service';
@Component({
selector: 'app-sign-in',
templateUrl: './sign-in.component.html',
styleUrls: ['./sign-in.component.scss'],
})
export class SignInComponent {
loading: boolean;
user: IUser;
constructor(private router: Router,
private cognitoService: CognitoService) {
this.loading = false;
this.user = {} as IUser;
}
public signIn(): void {
this.loading = true;
this.cognitoService.signIn(this.user)
.then(() => {
this.router.navigate(['/profile']);
}).catch(() => {
this.loading = false;
});
}
}
13.修改src/app/sign-in/sign-in.component.html文件。添加如下代码行。
<div class="row justify-content-center my-5">
<div class="col-4">
<div class="card">
<div class="card-body">
<div class="row">
<div class="col mb-2">
<label for="email" class="form-label">Email:</label>
<input type="email" id="email" name="email" #email="ngModel" [(ngModel)]="user.email" class="form-control form-control-sm">
</div>
</div>
<div class="row">
<div class="col mb-2">
<label for="password" class="form-label">Password:</label>
<div class="input-group input-group-sm">
<input [type]="user.showPassword ? 'text' : 'password'" id="password" name="password" #password="ngModel" [(ngModel)]="user.password" class="form-control form-control-sm">
<button type="button" class="btn btn-outline-secondary" (click)="user.showPassword = !user.showPassword">
<i class="bi" [ngClass]="{'bi-eye-fill': !user.showPassword, 'bi-eye-slash-fill': user.showPassword}"></i>
</button>
</div>
</div>
</div>
<div class="row">
<div class="col d-grid">
<button type="button" (click)="signIn()" class="btn btn-sm btn-success" [disabled]="loading">
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" *ngIf="loading"></span>
Sign in
</button>
</div>
</div>
</div>
</div>
</div>
</div>
14.创建ProfileComponent组件。
ng generate component profile --skip-tests=true
CREATE src/app/profile/profile.component.scss (0 bytes)
CREATE src/app/profile/profile.component.html (22 bytes)
CREATE src/app/profile/profile.component.ts (280 bytes)
UPDATE src/app/app.module.ts (726 bytes)
15.修改src/app/profile/profile.component.ts文件。导入CognitoService服务并创建update如下方法。
import { Component, OnInit } from '@angular/core';
import { IUser, CognitoService } from '../cognito.service';
@Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.scss'],
})
export class ProfileComponent implements OnInit {
loading: boolean;
user: IUser;
constructor(private cognitoService: CognitoService) {
this.loading = false;
this.user = {} as IUser;
}
public ngOnInit(): void {
this.cognitoService.getUser()
.then((user: any) => {
this.user = user.attributes;
});
}
public update(): void {
this.loading = true;
this.cognitoService.updateUser(this.user)
.then(() => {
this.loading = false;
}).catch(() => {
this.loading = false;
});
}
}
16.修改src/app/profile/profile.component.html文件。添加如下代码行。
<div class="row justify-content-center my-5">
<div class="col-4">
<div class="row">
<div class="col mb-2">
<label for="email" class="form-label">Email:</label>
<input type="email" id="email" name="email" #email="ngModel" [ngModel]="user.email" disabled class="form-control form-control-sm">
</div>
</div>
<div class="row">
<div class="col mb-2">
<label for="name" class="form-label">Name:</label>
<input type="text" id="name" name="name" #name="ngModel" [(ngModel)]="user.name" class="form-control form-control-sm">
</div>
</div>
<div class="row">
<div class="col d-grid">
<button type="button" (click)="update()" class="btn btn-sm btn-dark" [disabled]="loading">
<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true" *ngIf="loading"></span>
Update
</button>
</div>
</div>
</div>
</div>
17.修改src/app/app.component.ts文件。导入Router服务CognitoService和创建isAuthenticated方法,signOut如下所示。
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { CognitoService } from './cognito.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
isAuthenticated: boolean;
constructor(private router: Router,
private cognitoService: CognitoService) {
this.isAuthenticated = false;
}
public ngOnInit(): void {
this.cognitoService.isAuthenticated()
.then((success: boolean) => {
this.isAuthenticated = success;
});
}
public signOut(): void {
this.cognitoService.signOut()
.then(() => {
this.router.navigate(['/signIn']);
});
}
}
18.修改src/app/app.component.html文件并添加如下菜单。
<nav class="navbar navbar-expand-sm navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Angular Amazon Cognito</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div id="navbarContent" class="collapse navbar-collapse">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" routerLink="/signUp" routerLinkActive="active" *ngIf="!isAuthenticated">Sign up</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="/signIn" routerLinkActive="active" *ngIf="!isAuthenticated">Sign in</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="/profile" routerLinkActive="active" *ngIf="isAuthenticated">Profile</a>
</li>
<li class="nav-item">
<a class="nav-link" routerLink="" (click)="signOut()" *ngIf="isAuthenticated">Sign out</a>
</li>
</ul>
</div>
</div>
</nav>
<router-outlet></router-outlet>
19.修改src/app/app-routing.module.ts文件并添加如下路由。
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ProfileComponent } from './profile/profile.component';
import { SignInComponent } from './sign-in/sign-in.component';
import { SignUpComponent } from './sign-up/sign-up.component';
const routes: Routes = [
{
path: '',
redirectTo: 'signIn',
pathMatch: 'full',
},
{
path: 'profile',
component: ProfileComponent,
},
{
path: 'signIn',
component: SignInComponent,
},
{
path: 'signUp',
component: SignUpComponent,
},
{
path: '**',
redirectTo: 'signIn',
},
];
@NgModule({
imports: [
RouterModule.forRoot(routes),
],
exports: [
RouterModule,
],
})
export class AppRoutingModule {
}
20.修改src/app/app.module.ts文件。按如下方式导入模块FormsModule、ProfileComponent组件等。SignInComponentSignUpComponent
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ProfileComponent } from './profile/profile.component';
import { SignInComponent } from './sign-in/sign-in.component';
import { SignUpComponent } from './sign-up/sign-up.component';
@NgModule({
declarations: [
AppComponent,
ProfileComponent,
SignInComponent,
SignUpComponent,
],
imports: [
BrowserModule,
FormsModule,
AppRoutingModule,
],
providers: [
],
bootstrap: [
AppComponent,
],
})
export class AppModule {
}
21.使用以下命令运行应用程序。
npm start
> angular-cognito@1.0.0 start
> ng serve
✔ Browser application bundle generation complete.
Initial Chunk Files | Names | Raw Size
vendor.js | vendor | 9.98 MB |
styles.css, styles.js | styles | 486.91 kB |
polyfills.js | polyfills | 339.28 kB |
scripts.js | scripts | 76.33 kB |
main.js | main | 47.13 kB |
runtime.js | runtime | 6.87 kB |
| Initial Total | 10.91 MB
Build at: 2022-01-18T16:33:13.971Z - Hash: ce7a03498c95d4f5 - Time: 25230ms
** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
✔ Compiled successfully.
笔记:
- 运行该应用程序时可能会显示一些警告。
22.准备就绪!访问 URLhttp://localhost:4200/并检查应用程序是否正常运行。在GitHub Pages和Stackblitz上查看应用程序的运行情况。
该应用程序存储库可在https://github.com/rodrigokamada/angular-amazon-cognito获取。
测试应用程序
1.让我们测试一下这个应用程序。访问该网址http://localhost:4200/,填写电子邮件、密码字段,然后点击“注册”按钮。
2.检查用户是否已在 Amazon Cognito 中创建。
3.打开主题为“您的验证码”的电子邮件,并复制生成的代码,在我的例子中,代码308386是自动生成的。
4.在“代码”字段中填写复制的代码,然后单击“确认”按钮。
5.检查用户是否已在 Amazon Cognito 中得到确认。
6.在“电子邮件”、“密码”字段中填写信息,然后点击“登录”按钮。
7.在“姓名”字段中填写信息,然后点击“更新”按钮。
8.点击在 Amazon Cognito 中创建的用户链接。
9.检查 Amazon Cognito 中的用户名是否已更新。
10.准备就绪!我们测试用户登录、注册和更新功能。
结论
本文内容总结如下:
- 我们在亚马逊网络服务(AWS)上创建了一个账户。
- 我们在 Amazon Cognito 上创建并配置了一个用户池。
- 我们创建了一个Angular应用程序。
- 我们在 Angular 应用程序中添加了登录、注册和个人资料显示页面。
- 我们测试了 Angular 应用程序,并验证了用户在 Amazon Cognito 上的注册。
您可以参考本文,在提供访问控制的 Angular 应用程序中添加用户登录、注册和个人资料身份验证功能。
感谢阅读,希望您喜欢这篇文章!
这篇教程是用葡萄牙语发布在我的博客上的。
想及时了解我发布的最新文章,请在Twitter上关注我。
文章来源:https://dev.to/rodrigokamada/authentication-using-the-amazon-cognito-to-an-angular-application-ilh


































