在20分钟内创建一个带有身份验证的Angular应用

本文最初发布在OKTA开发人员博客上 。 感谢您支持使SitePoint成为可能的合作伙伴。

Angular(以前称为Angular 2.0)正迅速成为构建现代单页应用程序的最强大方法之一。 Angular的核心优势是致力于构建可重用组件,这有助于您消除应用程序中的各种问题。 以身份验证为例:构建它可能很麻烦,但是一旦将其包装在一个组件中,身份验证逻辑就可以在整个应用程序中重用。

Angular CLI使安装新组件甚至整个项目变得容易。 如果您还没有使用Angular CLI来快速生成Angular代码,那么您将大有收获!

在此示例中,您将使用Angular CLI(一个用于Angular开发的工具)构建一个简单的Web应用程序。 您将创建一个具有搜索和编辑功能的应用程序,然后添加身份验证。

创建一个Angular应用程序

提示:如果您想跳过构建Angular应用程序并直接添加身份验证,可以克隆我的ng-demo项目,然后跳到“ 在Okta中创建OpenID Connect应用程序”部分。

git clone https://github.com/mraible/ng-demo.git

您需要什么

  • 约20分钟
  • 最喜欢的文本编辑器或IDE。 我推荐IntelliJ IDEA
  • 已安装Node.js和npm。 我建议使用nvm
  • 安装了Angular CLI 。 如果您尚未安装Angular CLI,请使用npm install -g @angular/cli

使用ng new命令创建一个新项目:

ng new ng-demo

这将创建一个ng-demo项目并在其中运行npm install 。 大约需要一分钟才能完成,但是具体取决于您的连接速度。

[mraible:~/dev] $ ng new ng-demo
installing ng
  create .editorconfig
  create README.md
  create src/app/app.component.css
  create src/app/app.component.html
  create src/app/app.component.spec.ts
  create src/app/app.component.ts
  create src/app/app.module.ts
  create src/assets/.gitkeep
  create src/environments/environment.prod.ts
  create src/environments/environment.ts
  create src/favicon.ico
  create src/index.html
  create src/main.ts
  create src/polyfills.ts
  create src/styles.css
  create src/test.ts
  create src/tsconfig.app.json
  create src/tsconfig.spec.json
  create src/typings.d.ts
  create .angular-cli.json
  create e2e/app.e2e-spec.ts
  create e2e/app.po.ts
  create e2e/tsconfig.e2e.json
  create .gitignore
  create karma.conf.js
  create package.json
  create protractor.conf.js
  create tsconfig.json
  create tslint.json
Successfully initialized git.
Installing packages for tooling via npm.
Installed packages for tooling via npm.
You can `ng set --global packageManager=yarn`.
Project 'ng-demo' successfully created.
[mraible:~] 46s $

您可以通过ng --version查看正在使用的Angular CLI ng --version

$ ng --version
    _                      _                 ____ _     ___
   / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
  / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
 / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
/_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
               |___/
@angular/cli: 1.3.2
node: 8.4.0
os: darwin x64

运行您的Angular应用程序

该项目使用webpack dev server配置。 要启动它,请确保您位于ng-demo目录中,然后运行:

ng serve

您应该在http:// localhost:4200看到类似以下的屏幕。

在20分钟内创建一个带有身份验证的Angular应用_第1张图片

您可以确保新项目的测试通过,运行ng test

$ ng test
...
Chrome 60.0.3112 (Mac OS X 10.12.6): Executed 3 of 3 SUCCESS (0.239 secs / 0.213 secs)

添加搜索功能

要添加搜索功能,请在IDE或您喜欢的文本编辑器中打开项目。 对于IntelliJ IDEA,使用文件>新建项目>静态Web并指向ng-demo目录。

在终端窗口中,进入您的项目目录cd,然后运行以下命令。 这将创建一个搜索组件。

$ ng g component search
installing component
  create src/app/search/search.component.css
  create src/app/search/search.component.html
  create src/app/search/search.component.spec.ts
  create src/app/search/search.component.ts
  update src/app/app.module.ts

打开src/app/search/search.component.html并将其默认HTML替换为以下内容:

Search

{{searchResults | json}}

Angular的路由器文档提供了设置到刚刚生成的SearchComponent的路由所需的信息。 快速摘要:

src/app/app.module.ts ,添加一个appRoutes常量并将其导入@NgModule

import { Routes, RouterModule } from '@angular/router';

const appRoutes: Routes = [
  {path: 'search', component: SearchComponent},
  {path: '', redirectTo: '/search', pathMatch: 'full'}
];

@NgModule({
  ...
  imports: [
    ...
    RouterModule.forRoot(appRoutes)
  ]
  ...
})
export class AppModule { }

src/app/app.component.html ,调整占位符内容并添加标记以显示路由。

Welcome to {{title}}!

有了路由设置后,就可以继续编写搜索功能了。

如果您仍在运行ng serve ,则浏览器应会自动刷新。 如果不是,请导航至http:// localhost:4200。 您可能会看到黑屏。 打开JavaScript控制台,您将看到问题。

在20分钟内创建一个带有身份验证的Angular应用_第2张图片

要解决此问题,请打开src/app/app.module.ts并将FormsModule作为导入添加到@NgModule

import { FormsModule } from '@angular/forms';

@NgModule({
  ...
  imports: [
    ...
    FormsModule
  ]
  ...
})
export class AppModule { }

现在,您应该看到搜索表单。

在20分钟内创建一个带有身份验证的Angular应用_第3张图片

如果要为此组件添加CSS,请打开src/app/search/search.component.css并添加一些CSS。 例如:

:host {
  display: block;
  padding: 0 20px;
}

本节介绍了如何使用Angular CLI为基本Angular应用程序生成新组件。 下一节将向您展示如何创建和使用JSON文件和localStorage创建伪造的API。

要获取搜索结果,请创建一个SearchService ,该服务向JSON文件发出HTTP请求。 首先生成新服务。

$ ng g service search
installing service
  create src/app/search.service.spec.ts
  create src/app/search.service.ts
  WARNING Service is generated but not provided, it must be provided to be used

将生成的search.service.ts及其测试移至app/shared/search 。 您需要创建此目录。

mkdir -p src/app/shared/search
mv src/app/search.service.* src/app/shared/search/.

创建src/assets/data/people.json来保存数据。

[
  {
    "id": 1,
    "name": "Peyton Manning",
    "phone": "(303) 567-8910",
    "address": {
      "street": "1234 Main Street",
      "city": "Greenwood Village",
      "state": "CO",
      "zip": "80111"
    }
  },
  {
    "id": 2,
    "name": "Demaryius Thomas",
    "phone": "(720) 213-9876",
    "address": {
      "street": "5555 Marion Street",
      "city": "Denver",
      "state": "CO",
      "zip": "80202"
    }
  },
  {
    "id": 3,
    "name": "Von Miller",
    "phone": "(917) 323-2333",
    "address": {
      "street": "14 Mountain Way",
      "city": "Vail",
      "state": "CO",
      "zip": "81657"
    }
  }
]

修改src/app/shared/search/search.service.ts并在其构造函数中提供Http作为依赖项。 在同一文件中,创建一个getAll()方法来收集所有人员。 此外,定义将编组JSON的AddressPerson类。

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()
export class SearchService {
  constructor(private http: Http) {}

  getAll() {
    return this.http.get('assets/data/people.json')
        .map((res: Response) => res.json());
  }
}

export class Address {
  street: string;
  city: string;
  state: string;
  zip: string;

  constructor(obj?: any) {
    this.street = obj && obj.street || null;
    this.city = obj && obj.city || null;
    this.state = obj && obj.state || null;
    this.zip = obj && obj.zip || null;
  }
}

export class Person {
  id: number;
  name: string;
  phone: string;
  address: Address;

  constructor(obj?: any) {
    this.id = obj && Number(obj.id) || null;
    this.name = obj && obj.name || null;
    this.phone = obj && obj.phone || null;
    this.address = obj && obj.address || null;
  }
}

要使这些类可供组件使用,请编辑src/app/shared/index.ts并添加以下内容:

export * from './search/search.service';

创建此文件的原因是,您可以在一行上导入多个类,而不必在单独的行上导入每个类。

src/app/search/search.component.ts ,为这些类添加导入。

import { Person, SearchService } from '../shared';

现在,您可以添加querysearchResults变量。 在那里,修改构造函数以注入SearchService

export class SearchComponent implements OnInit {
  query: string;
  searchResults: Array;

  constructor(private searchService: SearchService) {}

然后实现search()方法来调用服务的getAll()方法。

search(): void {
  this.searchService.getAll().subscribe(
    data => { this.searchResults = data; },
    error => console.log(error)
  );
}

此时,您可能会在浏览器的控制台中看到以下消息。

ORIGINAL EXCEPTION: No provider for SearchService!

要从上方修复“无提供程序”错误,请更新app.module.ts以导入SearchService并将服务添加到提供程序列表中。 因为SearchService依赖于Http ,所以您还需要导入HttpModule

import { SearchService } from './shared';
import { HttpModule } from '@angular/http';

@NgModule({
  ...
  imports: [
    ...
    HttpModule
  ],
  providers: [SearchService],
  bootstrap: [AppComponent]
})

现在,单击搜索按钮应该可以了。 为了使结果看起来更好,请删除src/app/search/search.component.html中的

标签,并用替换它。 

Name Phone Address
{{person.name}} {{person.phone}} {{person.address.street}}
{{person.address.city}}, {{person.address.state}} {{person.address.zip}}

然后在src/app/search/search.component.css添加一些其他CSS,以改善其表布局。

table {
  margin-top: 10px;
  border-collapse: collapse;
}

th {
  text-align: left;
  border-bottom: 2px solid #ddd;
  padding: 8px;
}

td {
  border-top: 1px solid #ddd;
  padding: 8px;
}

现在,搜索结果看起来更好。

在20分钟内创建一个带有身份验证的Angular应用_第4张图片

但是,等等,您仍然没有搜索功能! 要添加搜索功能,请将search()方法添加到SearchService

import { Observable } from 'rxjs';

search(q: string): Observable {
  if (!q || q === '*') {
    q = '';
  } else {
    q = q.toLowerCase();
  }
  return this.getAll().map(data => data.filter(item => JSON.stringify(item).toLowerCase().includes(q)));
}

然后重构SearchComponent以使用其query变量来调用此方法。

search(): void {
  this.searchService.search(this.query).subscribe(
    data => { this.searchResults = data; },
    error => console.log(error)
  );
}

现在,搜索结果将通过您键入的查询值进行过滤。

本节介绍了如何获取和显示搜索结果。 下一节将以此为基础,并说明如何编辑和保存记录。

添加编辑功能

修改src/app/search/search.component.html以添加用于编辑人物的链接。

{{person.name}}

运行以下命令以生成EditComponent

$ ng g component edit
installing component
  create src/app/edit/edit.component.css
  create src/app/edit/edit.component.html
  create src/app/edit/edit.component.spec.ts
  create src/app/edit/edit.component.ts
  update src/app/app.module.ts

src/app/app.module.ts为此组件添加路由:

const appRoutes: Routes = [
  {path: 'search', component: SearchComponent},
  {path: 'edit/:id', component: EditComponent},
  {path: '', redirectTo: '/search', pathMatch: 'full'}
];

更新src/app/edit/edit.component.html以显示可编辑的表单。 您可能会注意到,我已经向大多数元素添加了id属性。 使用Protractor编写集成测试时,这使事情变得容易。

{{editName}}

{{person.id}}
Address:

,

修改EditComponent以导入模型和服务类,并使用SearchService来获取数据。

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Address, Person, SearchService } from '../shared';
import { Subscription } from 'rxjs';
import { ActivatedRoute, Router } from '@angular/router';

@Component({
  selector: 'app-edit',
  templateUrl: './edit.component.html',
  styleUrls: ['./edit.component.css']
})
export class EditComponent implements OnInit, OnDestroy {
  person: Person;
  editName: string;
  editPhone: string;
  editAddress: Address;

  sub: Subscription;

  constructor(private route: ActivatedRoute,
              private router: Router,
              private service: SearchService) {
  }

  ngOnInit() {
    this.sub = this.route.params.subscribe(params => {
      const id = + params['id']; // (+) converts string 'id' to a number
      this.service.get(id).subscribe(person => {
        if (person) {
          this.editName = person.name;
          this.editPhone = person.phone;
          this.editAddress = person.address;
          this.person = person;
        } else {
          this.gotoList();
        }
      });
    });
  }

  ngOnDestroy() {
    this.sub.unsubscribe();
  }

  cancel() {
    this.router.navigate(['/search']);
  }

  save() {
    this.person.name = this.editName;
    this.person.phone = this.editPhone;
    this.person.address = this.editAddress;
    this.service.save(this.person);
    this.gotoList();
  }

  gotoList() {
    if (this.person) {
      this.router.navigate(['/search', {term: this.person.name} ]);
    } else {
      this.router.navigate(['/search']);
    }
  }
}

修改SearchService以包含用于通过其ID查找人员并保存人员的函数。 当您在那里时,请修改search()方法以了解localStorage的更新对象。

search(q: string): Observable {
  if (!q || q === '*') {
    q = '';
  } else {
    q = q.toLowerCase();
  }
  return this.getAll().map(data => {
    const results: any = [];
    data.map(item => {
      // check for item in localStorage
      if (localStorage['person' + item.id]) {
        item = JSON.parse(localStorage['person' + item.id]);
      }
      if (JSON.stringify(item).toLowerCase().includes(q)) {
        results.push(item);
      }
    });
    return results;
  });
}

get(id: number) {
  return this.getAll().map(all => {
    if (localStorage['person' + id]) {
      return JSON.parse(localStorage['person' + id]);
    }
    return all.find(e => e.id === id);
  });
}

save(person: Person) {
  localStorage['person' + person.id] = JSON.stringify(person);
}

如果要使表单看起来更好一点,可以将CSS添加到src/app/edit/edit.component.css

:host {
  display: block;
  padding: 0 20px;
}

button {
  margin-top: 10px;
}

此时,您应该可以搜索一个人并更新其信息。

在20分钟内创建一个带有身份验证的Angular应用_第5张图片

src/app/edit/edit.component.html

调用save()函数来更新一个人的数据。 您已经在上面实现了这一点。
该函数调用gotoList()函数,该函数将用户的名字发送回搜索屏幕时,将人的名字附加到URL上。

gotoList() {
  if (this.person) {
    this.router.navigate(['/search', {term: this.person.name} ]);
  } else {
    this.router.navigate(['/search']);
  }
}

由于执行此URL时SearchComponent不会自动执行搜索,因此请在其构造函数中添加以下逻辑来执行此操作。

import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';
...

sub: Subscription;

constructor(private searchService: SearchService, private route: ActivatedRoute) {
  this.sub = this.route.params.subscribe(params => {
    if (params['term']) {
      this.query = decodeURIComponent(params['term']);
      this.search();
    }
  });
}

您将要实现OnDestroy并定义ngOnDestroy方法来清理此预订。

import { Component, OnInit, OnDestroy } from '@angular/core';

export class SearchComponent implements OnInit, OnDestroy {
...
  ngOnDestroy() {
    this.sub.unsubscribe();
  }
}

进行所有这些更改之后,您应该能够搜索/编辑/更新一个人的信息。 如果可行–做得好!

表格验证

您可能会注意到的一件事是,您可以清除表单中的任何输入元素并将其保存。 至少,必须输入name字段。 否则,搜索结果中没有任何可单击的内容。

要使名称为必需,请修改edit.component.html以将required属性添加到名称


您还需要将所有内容包装在元素中。 在

标记之后添加 ,并在最后一个

之前将其关闭。 您还需要向表单添加一个(ngSubmit)处理函数,并将保存按钮更改为常规的提交按钮。

{{editName}}

...

进行这些更改后,将需要具有required属性的任何字段。

在20分钟内创建一个带有身份验证的Angular应用_第6张图片

在此屏幕截图中,您可能会注意到地址字段为空白。 控制台中的错误说明了这一点。

If ngModel is used within a form tag, either the name attribute must be set or the form
control must be defined as 'standalone' in ngModelOptions.

Example 1: 
Example 2: 

要解决此问题,请将name属性添加到所有地址字段。 例如:


,

现在,值应显示在所有字段中,并且name是必需的。

在20分钟内创建一个带有身份验证的Angular应用_第7张图片

如果要提供自己的验证消息而不是依赖浏览器的验证消息,请完成以下步骤:

  1. 删除ngNativeValidate并将#editForm="ngForm"添加到
    元素。
  2. #name="ngModel"添加到元素。
  3. [disabled]="!editForm.form.valid"到“ 保存”按钮。
  4. name字段下添加以下内容以显示验证错误。
Name is required

要了解有关表单和验证的更多信息,请参阅Angular表单文档 。

在Okta中创建OpenID Connect应用程序

OpenID Connect(OIDC)建立在OAuth 2.0协议之上。 它允许客户端验证用户的身份,以及获取其基本配置文件信息。 要了解更多信息,请参阅https://openid.net/connect 。

要集成Okta进行用户身份验证,您首先需要注册并创建OIDC应用程序。

登录到您的Okta帐户,如果没有,请创建一个。 导航到应用程序 ,然后单击添加应用程序按钮。 选择SPA并单击Next 。 在下一页上,将http://localhost:4200指定为基本URI,登录重定向URI和注销重定向URI。 单击完成 ,您应该看到类似以下的设置。

在20分钟内创建一个带有身份验证的Angular应用_第8张图片

安装Manfred Steyer的项目,以使用npm 添加OAuth 2和OpenID Connect支持 。

npm install --save angular-oauth2-oidc

修改src/app/app.component.ts以导入OAuthService并配置您的应用程序以使用Okta应用程序的设置。

import { OAuthService, JwksValidationHandler } from 'angular-oauth2-oidc';

...

  constructor(private oauthService: OAuthService) {
    this.oauthService.redirectUri = window.location.origin;
    this.oauthService.clientId = '{client-id}';
    this.oauthService.scope = 'openid profile email';
    this.oauthService.issuer = 'https://dev-{dev-id}.oktapreview.com';
    this.oauthService.tokenValidationHandler = new JwksValidationHandler();

    // Load Discovery Document and then try to login the user
    this.oauthService.loadDiscoveryDocument().then(() => {
      this.oauthService.tryLogin();
    });
  }
...

创建src/app/home/home.component.ts并将其配置为具有“ 登录”和“ 注销”按钮。

import { Component } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';

@Component({
  template: `
    

Welcome, {{givenName}}!

Search

` }) export class HomeComponent { constructor(private oauthService: OAuthService) { } login() { this.oauthService.initImplicitFlow(); } logout() { this.oauthService.logOut(); } get givenName() { const claims = this.oauthService.getIdentityClaims(); if (!claims) { return null; } return claims['name']; } }

创建src/app/shared/auth/auth.guard.service.ts导航到HomeComponent如果用户不被认证。

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { OAuthService } from 'angular-oauth2-oidc';

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private oauthService: OAuthService, private router: Router) {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    if (this.oauthService.hasValidIdToken()) {
      return true;
    }

    this.router.navigate(['/home']);
    return false;
  }
}

出口AuthGuardsrc/shared/index.ts

export * from './auth/auth.guard.service';

导入OAuthModulesrc/app/app.module.ts ,配置新的HomeComponent ,并锁定/search/edit路线打倒AuthGuard

import { OAuthModule } from 'angular-oauth2-oidc';
import { HomeComponent } from './home/home.component';
import { SearchService, AuthGuard } from './shared';

const appRoutes: Routes = [
  {path: 'search', component: SearchComponent, canActivate: [AuthGuard]},
  {path: 'edit/:id', component: EditComponent, canActivate: [AuthGuard]},
  {path: 'home', component: HomeComponent},
  {path: '', redirectTo: 'home', pathMatch: 'full'},
  {path: '**', redirectTo: 'home'}
];

@NgModule({
  declarations: [
    ...
    HomeComponent
  ],
  imports: [
    ...
    OAuthModule.forRoot()
  ],
  providers: [
    AuthGuard,
    SearchService
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

进行这些更改之后,您应该可以运行ng serve并看到一个登录按钮。

在20分钟内创建一个带有身份验证的Angular应用_第9张图片

单击“ 登录”按钮,然后使用Okta应用程序中配置的人员之一登录

在20分钟内创建一个带有身份验证的Angular应用_第10张图片

登录后,您将可以单击搜索并查看人们的信息。

在20分钟内创建一个带有身份验证的Angular应用_第11张图片

如果可行,那就太好了! 如果要在应用程序中构建自己的登录表单,请继续阅读以了解如何将Okta Auth SDK与OAuthService

使用Okta Auth SDK进行身份验证

Okta Auth SDK建立在Otka的Authentication API和OAuth 2.0 API的基础上 ,使您能够使用JavaScript创建完全品牌化的登录体验。

使用npm安装它:

npm install @okta/okta-auth-js --save

.angular-cli.json添加对该库的主要JavaScript文件.angular-cli.json

"scripts": [
  "../node_modules/@okta/okta-auth-js/dist/okta-auth-js.min.js"
],

本节中的组件使用Bootstrap CSS类。 安装Bootstrap 4。

npm install [email protected] --save

修改src/styles.css以添加对Bootstrap的CSS文件的引用。

@import "~bootstrap/dist/css/bootstrap.css";

更新src/app/app.component.html以将Bootstrap类用于其导航栏和网格系统。


创建src/app/shared/auth/okta.auth.wrapper.ts来包装Okta Auth SDK并将其与OAuthService集成。 它的login()方法使用OktaAuth获取会话令牌并将其交换为ID和访问令牌。

import { OAuthService } from 'angular-oauth2-oidc';
import { Injectable } from '@angular/core';

declare const OktaAuth: any;

@Injectable()
export class OktaAuthWrapper {

  private authClient: any;

  constructor(private oauthService: OAuthService) {
    this.authClient = new OktaAuth({
      url: this.oauthService.issuer
    });
  }

  login(username: string, password: string): Promise {
    return this.oauthService.createAndSaveNonce().then(nonce => {
      return this.authClient.signIn({
        username: username,
        password: password
      }).then((response) => {
        if (response.status === 'SUCCESS') {
          return this.authClient.token.getWithoutPrompt({
            clientId: this.oauthService.clientId,
            responseType: ['id_token', 'token'],
            scopes: ['openid', 'profile', 'email'],
            sessionToken: response.sessionToken,
            nonce: nonce,
            redirectUri: window.location.origin
          })
            .then((tokens) => {
              const idToken = tokens[0].idToken;
              const accessToken = tokens[1].accessToken;
              const keyValuePair = `#id_token=${encodeURIComponent(idToken)}&access_token=${encodeURIComponent(accessToken)}`;
              return this.oauthService.tryLogin({ <1>
                customHashFragment: keyValuePair,
                disableOAuth2StateCheck: true
              });
            });
        } else {
          return Promise.reject('We cannot handle the ' + response.status + ' status');
        }
      });
    });
  }
}

在上面的代码中, oauthService.tryLogin()解析并存储idTokenaccessToken以便可以使用OAuthService.getIdToken()OAuthService.getAccessToken()进行检索。

出口OktaAuthWrappersrc/shared/index.ts

export * from './auth/okta.auth.wrapper';

添加OktaAuthWrapper作为一个供应商app.module.ts

import { SearchService, AuthGuard, OktaAuthWrapper } from './shared';

@NgModule({
  ...
  providers: [
    ...
    OktaAuthWrapper
  ],
  bootstrap: [AppComponent]
})

更改HomeComponent申报OktaAuth并修改其template所以它有一个按钮来登录,以及一个登录表单。

@Component({
  template: `
    

Welcome, {{givenName}}!

Search

Login with Authorization Server

Login with Username/Password

Login wasn't successful.

` })

进行这些更改后, HomeComponent应该呈现如下。

在20分钟内创建一个带有身份验证的Angular应用_第12张图片

添加局部变量的用户名和密码字段,进口OktaAuthWrapper ,并实施loginWithPassword()的方法HomeComponent

import { OktaAuthWrapper } from '../shared';
...

username;
password;

constructor(private oauthService: OAuthService,
            private oktaAuthWrapper: OktaAuthWrapper) {
}

loginWithPassword() {
  this.oktaAuthWrapper.login(this.username, this.password)
    .then(_ => console.debug('logged in'))
    .catch(err => console.error('error logging in', err));
}

您应该能够使用应用程序的注册用户之一使用该表单登录。 登录后,您将可以单击“ 搜索”链接并查看人们的信息。

在20分钟内创建一个带有身份验证的Angular应用_第13张图片

角+ Okta

如果一切正常–恭喜! 如果遇到问题,请使用okta标签将问题发布到Stack Overflow,或在Twitter @mraible上打我。

您可以在GitHub上的此博客文章中找到该应用程序的完整版本。 要了解有关Angular安全性的更多信息,请参阅Angular的安全性文档 。 如果您想了解有关OpenID Connect的更多信息,建议您观看下面的舒缓视频。

From: https://www.sitepoint.com/angular-authentication-oidc/

你可能感兴趣的:(json,git,javascript,ViewUI)