内容列表
Auth WorkflowProject SetupAuth ComponentBootstrap StyleAuth Service Sanity CheckUser LoginUser Registration Server-side SetupSanity CheckAuth LoginAuth RegisterLocal StorageUser StatusRoute RestrictionWhat’s Next?
在这篇文章中,我们将示范怎样通过Angular 4和Flask设置token基础认证。
主要依赖:
1、Angular v4.2.4(通过Angular CLI v1.3.2)
2、Flask v0.12
3、Python v3.6.2
认证流程
这里是所有用户认证过程:
1、客户端登录并且将凭证发送到服务端。
2、如果凭证正确,服务生成一个token并且响应到客户端。
3、客户端接收并且存储token进本地缓存。
4、在后面的请求客户端带着请求参数头信息发送token到服务端。
项目安装:
开始安装Angular CLI:
$ npm install -g @angular/cli@1.3.2
生成新的Angular 4样板项目:
$ ng new angular4-auth
在安装依赖之后启动APP
$ cd angular4-auth$ ng serve
它将花一到两分钟去编译和构建你的应用程序,一旦完成,输入http://localhost:4200确信app已经启动和运行。
用编辑工具打开你的项目,然后扫视一下你的代码:
├── e2e│ ├── app.e2e-spec.ts│ ├── app.po.ts│ └── tsconfig.e2e.json├── karma.conf.js├── package.json├── protractor.conf.js├── src│ ├── app│ │ ├── ponent.css│ │ ├── ponent.html│ │ ├── ponent.spec.ts│ │ ├── ponent.ts│ │ └── app.module.ts│ ├── assets│ ├── environments│ │ ├── environment.prod.ts│ │ └── environment.ts│ ├── favicon.ico│ ├── index.html│ ├── main.ts│ ├── polyfills.ts│ ├── styles.css│ ├── test.ts│ ├── tsconfig.app.json│ ├── tsconfig.spec.json│ └── typings.d.ts├── tsconfig.json└── tslint.json
总之,客户端代码存放在src目录下,且Angular app 它自己能在app文件夹下发现它。
注意app.module.ts中的AppModule。这个通常是Angular app的引导程序。@NgModule注解获取源数据让Angular知道怎么样去运行APP。
在这边文章中我们创建的每一件事都将添加到这个项目。
在移动以前你确信你已经理解这个app的结构。
你注意到了CLI初始化一个新的GIT repo?这个部分是可选的,但是创建一个新的Github库和远程更新是一个好的主意:
$ git remote set-url origin <newurl>
现在,开始装载一个新的组件。。。
认证组件:
首先,使用CLI去生成一个新的登录组件:
$ ng generate component components/login
这个安装了一个组件文件和文件夹,甚至写入到app.module.ts。接下来,按如下来修改
import { Component } from '@angular/core';@Component({selector: 'login',templateUrl: './ponent.html',styleUrls: ['./ponent.css']})export class LoginComponent {test: string = 'just a test';}
如果你之前没有使用TypeScript,这段代码看起来对你非常不相关。TypeScript静态类型的javascript超集,编译成vanilla JavaScript,它事实上是构建Angular 4 apps的程序语言。
在Angular4,我们通过@Component注解封装的一个配置对象到一个组件。我们能通过导入我们需要的类在包之间共享代码;并且在这种情况下,我们从@angular/core包中导入组件。LoginComponent类是一个controller组件,并且对于其他导入的类我们使用export操作使它可用。
添加如下HTML到ponent.html
<h1>Login</h1><p>{{test}}</p>
接下来,在app.module.ts文件中通过RouterModule配置路由
import { BrowserModule } from '@angular/platform-browser';import { NgModule } from '@angular/core';import { RouterModule } from '@angular/router';import { AppComponent } from './ponent';import { LoginComponent } from './components/login/ponent';@NgModule({declarations: [AppComponent,LoginComponent,],imports: [BrowserModule,RouterModule.forRoot([{ path: 'login', component: LoginComponent }])],providers: [],bootstrap: [AppComponent]})export class AppModule { }
最后在ponent.html文件中用<router-outlet>标签替代所有的HTML启用路由:
<router-outlet></router-outlet>
在你的终端运行ng服务,如果你已经启动,在导航栏中输入http://localhost:4200/login.如果一切正常,你应该看到一个 test 文本。
Bootstrap Style
快速添加一些样式,更新index.html,添加到Bootstrap并且在一个容器中添加<app-root></app-root>标签。
<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Angular4Auth</title><base href="/"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="icon" type="image/x-icon" href="favicon.ico"><link rel="stylesheet" href="///bootstrap/3.3.7/css/bootstrap.min.css"></head><body><div class="container"><app-root></app-root></div></body></html>
一旦你保存,你就会看到app自动重载。
认证服务
接下来,我们创建一个全局服务去进行用户登录,用户注销,用户签名:
$ ng generate service services/auth
编辑auth.service.ts写入如下代码:
import { Injectable } from '@angular/core';@Injectable()export class AuthService {test(): string {return 'working';}}
记住在Angular 1中怎样提供工作的?它们是一个存储单态的全局对象。当一个供应者数据发生改变,注入该提供者的任何对象都将接收更新。在angular 4,供应者保持它们特有的行为并且他们使用@Injectable注解定义。
明智的检查
在添加任何有意义的事物到AuthService之前。让我们确信该服务自己已经正确装载,这样做,在ponent.ts中注入服务并且调用test()方法:
import { Component, OnInit } from '@angular/core';import { AuthService } from '../../services/auth.service';@Component({selector: 'login',templateUrl: './ponent.html',styleUrls: ['./ponent.css']})export class LoginComponent implements OnInit {test: string = 'just a test';constructor(private auth: AuthService) {}ngOnInit(): void {console.log(this.auth.test());}}
我们介绍一些新概念和关键字。constructor()功能是一个指定的方法,我们通常用它来实例化一个类。constructor()的作用是我们可以传入需要的参数到类中,包括我们想注入的任何供应者(i.e.,AuthService)。在TypeScript中,我们能用private关键字对外隐藏内部变量。在构造函数中通过一个私有变量快速的在类中定义属性,并且赋值给这个参数值。注意的是在它赋值给构造函数的时候这个对象如何访问身份验证变量。
我们实现OnInit接口确保我们明确的定义了一个ngOnInit()功能。实现OnInit确保我们的组件在第一次探测到改变之后被调用。当这个组件首先被初始化时该功能将被调用,使它成为依赖其他angular类配置数据的理想场所。
不像组件,被自动添加,服务不得不手动的导入并且在@NgModule配置。因此,为了让它工作,你将不得不在app.module.ts中导入AuthService和添加它到providers:
import { BrowserModule } from '@angular/platform-browser';import { NgModule } from '@angular/core';import { RouterModule } from '@angular/router';import { AppComponent } from './ponent';import { LoginComponent } from './components/login/ponent';import { AuthService } from './services/auth.service';@NgModule({declarations: [AppComponent,LoginComponent,],imports: [BrowserModule,RouterModule.forRoot([{ path: 'login', component: LoginComponent }])],providers: [AuthService],bootstrap: [AppComponent]})export class AppModule { }
运行服务并且导航中输入http://localhost:4200/login。你应该在JavaScript控制台看到工作日志输出。
用户登录
手工登录一个用户,按照如下更新AuthService:
import { Injectable } from '@angular/core';import { Headers, Http } from '@angular/http';import 'rxjs/add/operator/toPromise';@Injectable()export class AuthService {private BASE_URL: string = 'http://localhost:5000/auth';private headers: Headers = new Headers({'Content-Type': 'application/json'});constructor(private http: Http) {}login(user): Promise<any> {let url: string = `${this.BASE_URL}/login`;return this.http.post(url, user, {headers: this.headers}).toPromise();}}
我们使用一些内置Angular帮助类,Headers和Http,控制我们的ajax调用服务。
同时,更新app.module.ts导入HttpModule。
import { BrowserModule } from '@angular/platform-browser';import { NgModule } from '@angular/core';import { RouterModule } from '@angular/router';import { HttpModule } from '@angular/http';import { AppComponent } from './ponent';import { LoginComponent } from './components/login/ponent';import { AuthService } from './services/auth.service';@NgModule({declarations: [AppComponent,LoginComponent,],imports: [BrowserModule,HttpModule,RouterModule.forRoot([{ path: 'login', component: LoginComponent }])],providers: [AuthService],bootstrap: [AppComponent]})export class AppModule { }
这里,我们使用Http服务去发送一个ajax请求/user/login终端。它将返回一个响应的对象。
用户注册
让我们回到前面并且添加了一些注册用户的功能,类似用户登录。更新src/app/services/auth.service.ts,需要注意的是register方法:
import { Injectable } from '@angular/core';import { Headers, Http } from '@angular/http';import 'rxjs/add/operator/toPromise';@Injectable()export class AuthService {private BASE_URL: string = 'http://localhost:5000/auth';private headers: Headers = new Headers({'Content-Type': 'application/json'});constructor(private http: Http) {}login(user): Promise<any> {let url: string = `${this.BASE_URL}/login`;return this.http.post(url, user, {headers: this.headers}).toPromise();}register(user): Promise<any> {let url: string = `${this.BASE_URL}/register`;return this.http.post(url, user, {headers: this.headers}).toPromise();}}
现在,为了测试我们需要启动后端。。。
服务端启动
对于服务端,我们将使用前面博客完成的项目,Token-Based Authentication With Flask.你可以从flask-jwt-auth库中查看代码。
在一个新的终端中克隆项目结构:
$ git clone /realpython/flask-jwt-auth
在README中的指示安装项目,在移动之前确信能通过测试。一旦完成,用python的manage.py启动服务端,将监听5000端口。
明智检查
为了测试,从服务端更新LoginComponent的login和register方法:
import { Component, OnInit } from '@angular/core';import { AuthService } from '../../services/auth.service';@Component({selector: 'login',templateUrl: './ponent.html',styleUrls: ['./ponent.css']})export class LoginComponent implements OnInit {test: string = 'just a test';constructor(private auth: AuthService) {}ngOnInit(): void {let sampleUser: any = {email: 'michael@' as string,password: 'michael' as string};this.auth.register(sampleUser).then((user) => {console.log(user.json());}).catch((err) => {console.log(err);});this.auth.login(sampleUser).then((user) => {console.log(user.json());}).catch((err) => {console.log(err);});}}
在浏览器中刷新http://localhost:4200/login,在用户登录后,你应该在javascript控制台中看到带有token的成功输出:
{"auth_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1M…jozfQ.bPNQb3C98yyNe0LDyl1Bfkp0Btn15QyMxZnBoE9RQMI","message": "Successfully logged in.","status": "success"}
注意:文章到这里还没有完,由于篇幅限制,完整内容请到hongfu951博客上查看
完整内容URL地址:用Angular 4和Flask进行用户验证【翻译】
欢迎访问:博客,查看更多文章