gpt4 book ai didi

详解在ASP.NET Core中使用Angular2以及与Angular2的Token base身份认证

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 26 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章详解在ASP.NET Core中使用Angular2以及与Angular2的Token base身份认证由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

Angular2是对Angular1的一次彻底的,破坏性的更新.

相对于Angular1.x,借用某果的广告语,唯一的不同,就是处处都不同.

•首先,推荐的语言已经不再是Javascript,取而代之的TypeScript,(TypeScript = ES6 + 类型系统 + 类型注解), TypeScriipt的类型系统对于开发复杂的单页Web app大有帮助,同时编译成javascript后的执行效率也比大多数手写javascript要快。有兴趣的同学可以查阅官方文档:英文传送门 |中文传送门.

•得益于彻底重构,性能相对于Angular1.x有了大幅提升,也更适合再全平台部署.

•Angular2是基于Component的,Component可以理解为是1.x时代的Controller + $Scope + view 。

•View的很多语法也做了更新,比如<li ng-repeat="movie in vm.movies"></li> 变成了 <li *ngFor="let movie of movies"></li> 。

关于Angular2,强烈建议查阅官方文档:英文传送门| 中文传送门 。

注意:本文章属于Step by step + Code Sample教程,且篇幅较长,建议下载本Sample并跟着本文进度自己重做一遍本例,下载完整代码并分析代码结构才有意义,下载地址:How to authorization Angular 2 app with asp.net core web api 。

1.前期准备 。

•推荐使用VS2015 Update3或更新的版本完成本示例 。

•你需要安装.NET Core开发环境,这里提供VS版: //www.zzvips.com/softs/472362.html 。

•安装Node.js 版本5.0.0或以上,(在本例中,这个主要是编译TypeScript用的)下载地址:Node.js and NPM 。

•NPM 3.0.0或以上,默认NPM会随着Node.js一并安装完毕。(在本例中,这个主要是下载各种Angular的各个包用的,参考VS中的Nuget) 。

2.创建项目 。

在VS中新建项目,项目类型选择 ASP.NET Core Web Application(.Net Core),输入项目名称为:CSAuthorAngular2InASPNetCore,Template选择为Empty. 。

3.在项目中整合Angular2 。

3.1.配置Startup.cs 。

注:添加下面的代码时IDE会报代码错误,这是因为还没有引用对用的包,进入报错的这一行,点击灯泡,加载对应的包就可以了.

详解在ASP.NET Core中使用Angular2以及与Angular2的Token base身份认证

(图文无关) 。

在ConfigureServices中添加如下代码 。

?
1
services.AddMvc();

这里是添加MVC服务 。

在Configure中添加如下代码 。

?
1
2
3
4
5
6
7
8
app.UseStaticFiles();
 
app.UseMvc(routes =>
{
   routes.MapRoute(
     name: "default" ,
     template: "{controller=Home}/{action=Index}" );
});

第一句是启用静态文件,第二句是应用MVC模式并添加路由配置.

完整的代码应该是这个样子 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Startup
{
   // This method gets called by the runtime. Use this method to add services to the container.
   // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
   public void ConfigureServices(IServiceCollection services)
   {
     services.AddMvc();
   }
 
   // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
   public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
   {
     app.UseStaticFiles();
 
     app.UseMvc(routes =>
     {
       routes.MapRoute(
         name: "default" ,
         template: "{controller=Home}/{action=Index}" );
     });
   }
}

3.2.添加控制器以及视图 。

3.2.1.在项目根目录下添加Controllers目录,并在其中添加一个控制器HomeController.cs,默认代码即可.

3.2.2.在项目跟目录下创建Views目录,在Views目录中新建目录Home, 最后在Home目录中新建视图Index.cshtml,内容应该是这样:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
< html >
< head >
   < title >Angular QuickStart</ title >
   < base href = "/" >
   < meta charset = "UTF-8" >
   < meta name = "viewport" content = "width=device-width, initial-scale=1" >
   <!-- 1. Load libraries -->
   <!-- Polyfill(s) for older browsers -->
   < script src = "node_modules/core-js/client/shim.min.js" ></ script >
   < script src = "node_modules/zone.js/dist/zone.js" ></ script >
   < script src = "node_modules/reflect-metadata/Reflect.js" ></ script >
   < script src = "node_modules/systemjs/dist/system.src.js" ></ script >
   <!-- 2. Configure SystemJS -->
   < script src = "systemjs.config.js" ></ script >
   < script >
    System.import('app').catch(function(err){ console.error(err); });
   </ script >
</ head >
<!-- 3. Display the application -->
< body >
   < my-app >Loading...</ my-app >
</ body >
</ html >

现在运行项目的话你仅仅能看到一个Loading,再控制台中你还能看到错误,这是因为我们还没有配置Angular。让我们前往wwwroot目录.

3.3.在项目的wwwroot目录中添加如下结构

3.3.1搭建Angular2基础环境 。

•package.json 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
{
  "name" : "angular-quickstart" ,
  "version" : "1.0.0" ,
  "scripts" : {
   "start" : "tsc && concurrently \"tsc -w\" \"lite-server\" " ,
   "lite" : "lite-server" ,
   "postinstall" : "typings install" ,
   "tsc" : "tsc" ,
   "tsc:w" : "tsc -w" ,
   "typings" : "typings"
  },
  "licenses" : [
   {
    "type" : "MIT" ,
    "url" : "https://github.com/angular/angular.io/blob/master/LICENSE"
   }
  ],
  "dependencies" : {
   "@angular/common" : "2.0.2" ,
   "@angular/compiler" : "2.0.2" ,
   "@angular/core" : "2.0.2" ,
   "@angular/forms" : "2.0.2" ,
   "@angular/http" : "2.0.2" ,
   "@angular/platform-browser" : "2.0.2" ,
   "@angular/platform-browser-dynamic" : "2.0.2" ,
   "@angular/router" : "3.0.2" ,
   "@angular/upgrade" : "2.0.2" ,
   "angular-in-memory-web-api" : "0.1.5" ,
   "bootstrap" : "3.3.7" ,
   "core-js" : "2.4.1" ,
   "reflect-metadata" : "0.1.8" ,
   "rxjs" : "5.0.0-beta.12" ,
   "systemjs" : "0.19.39" ,
   "zone.js" : "0.6.25"
  },
  "devDependencies" : {
   "concurrently" : "3.0.0" ,
   "gulp" : "^3.9.1" ,
   "lite-server" : "2.2.2" ,
   "typescript" : "2.0.3" ,
   "typings" : "1.4.0"
  }
}

•systemjs.config.js 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
( function (global) {
   System.config({
     paths: {
       // paths serve as alias
       'npm:' : 'node_modules/'
     },
     // map tells the System loader where to look for things
     map: {
       // our app is within the app folder
       app: 'app' ,
       // angular bundles
       '@angular/core' : 'npm:@angular/core/bundles/core.umd.js' ,
       '@angular/common' : 'npm:@angular/common/bundles/common.umd.js' ,
       '@angular/compiler' : 'npm:@angular/compiler/bundles/compiler.umd.js' ,
       '@angular/platform-browser' : 'npm:@angular/platform-browser/bundles/platform-browser.umd.js' ,
       '@angular/platform-browser-dynamic' : 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js' ,
       '@angular/http' : 'npm:@angular/http/bundles/http.umd.js' ,
       '@angular/router' : 'npm:@angular/router/bundles/router.umd.js' ,
       '@angular/forms' : 'npm:@angular/forms/bundles/forms.umd.js' ,
       '@angular/upgrade' : 'npm:@angular/upgrade/bundles/upgrade.umd.js' ,
       // other libraries
       'rxjs' : 'npm:rxjs' ,
       'angular-in-memory-web-api' : 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
     },
     // packages tells the System loader how to load when no filename and/or no extension
     packages: {
       app: {
         main: './main.js' ,
         defaultExtension: 'js'
       },
       rxjs: {
         defaultExtension: 'js'
       }
     }
   });
})( this );

•tsconfig.js 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
  "compileOnSave" : true ,
  "compilerOptions" : {
   "target" : "es5" ,
   "module" : "commonjs" ,
   "moduleResolution" : "node" ,
   "sourceMap" : true ,
   "emitDecoratorMetadata" : true ,
   "experimentalDecorators" : true ,
   "removeComments" : false ,
   "noImplicitAny" : false
  },
  "exclude" : [
   "node_modules"
  ]
}

•typings.json(注,在最新文档中typings已被npm的@types替代,参见官方文档:文档变更日志) 。

?
1
2
3
4
5
6
7
{
  "globalDependencies" : {
   "core-js" : "registry:dt/core-js#0.0.0+20160725163759" ,
   "jasmine" : "registry:dt/jasmine#2.2.0+20160621224255" ,
   "node" : "registry:dt/node#6.0.0+20160909174046"
  }
}

右击wwwroot中的Package.json,选择Restore Packages(或者在CMD下进入wwwroot目录,并执行命令 npm install),npm会去下载需要的包,并存储于node_modules目录中.

详解在ASP.NET Core中使用Angular2以及与Angular2的Token base身份认证

3.3.2.配置启动文件以启用Angular2 。

在wwwroot下新建目录app,app拥有如下文件:

•app.component.ts 。

?
1
2
3
4
5
6
7
8
9
import { Component } from '@angular/core' ;
 
@Component({
   moduleId: module.id,
   selector: 'my-app' ,
   template: "this is in angular2" ,
})
export class AppComponent {
}

可以发现被@Component装饰属性装饰了AppComponent,selector指代你Component的占位符,比如本例中你可以再Home/index.cshtml中发现一段这样的标记 。

?
1
< my-app >Loading...</ my-app >

template既为该Component的View,不要忘记moduleId,不添加它会出现很多奇怪的问题.

•app.module.ts 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { NgModule } from "@angular/core" ;
import { BrowserModule } from "@angular/platform-browser" ;
 
import { AppComponent } from "./app.component" ;
 
@NgModule({
   bootstrap: [AppComponent],
   imports: [
     BrowserModule
   ],
   declarations: [
     AppComponent
   ]
})
export class AppModule { }

•main.ts 。

?
1
2
3
4
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' ;
import { AppModule } from './app.module' ;
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);

基础整合完毕.

按F5 Debug一下,现在你能再浏览器中看到一句话:this is in angular 2 。

详解在ASP.NET Core中使用Angular2以及与Angular2的Token base身份认证

4.实现身份认证 。

废了半天劲,看着很傻,没有任何成就感。怎么办,让我们再深入一点,接下来我们来为Angular2完成一个Token base的身份验证,我会把Angular2的routing,data bind,service,http,等等你工作中最常用到的挨个演示一遍.

4.1.Server端 。

4.1.1.创建一些辅助类 。

4.1.1.1.在项目根目录下创建一个文件夹Auth,并添加RSAKeyHelper.cs以及TokenAuthOption.cs两个文件 。

•在RSAKeyHelper.cs中 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System.Security.Cryptography;
 
namespace CSTokenBaseAuth.Auth
{
   public class RSAKeyHelper
   {
     public static RSAParameters GenerateKey()
     {
       using (var key = new RSACryptoServiceProvider(2048))
       {
         return key.ExportParameters( true );
       }
     }
   }
}

•在TokenAuthOption.cs中 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System;
using Microsoft.IdentityModel.Tokens;
 
namespace CSTokenBaseAuth.Auth
{
   public class TokenAuthOption
   {
     public static string Audience { get ; } = "ExampleAudience" ;
     public static string Issuer { get ; } = "ExampleIssuer" ;
     public static RsaSecurityKey Key { get ; } = new RsaSecurityKey(RSAKeyHelper.GenerateKey());
     public static SigningCredentials SigningCredentials { get ; } = new SigningCredentials(Key, SecurityAlgorithms.RsaSha256Signature);
 
     public static TimeSpan ExpiresSpan { get ; } = TimeSpan.FromMinutes(20);
   }
}

4.1.1.2.在项目根目录下创建目录Model,并在其中添加RequestResult.cs,代码应该是这样.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public class RequestResult
{
   public RequestState State { get ; set ; }
   public string Msg { get ; set ; }
   public Object Data { get ; set ; }
}
 
public enum RequestState
{
   Failed = -1,
   NotAuth = 0,
   Success = 1
}

4.1.2更新Startup.cs 。

在ConfigureServices中添加如下代码:

?
1
2
3
4
5
6
services.AddAuthorization(auth =>
{
   auth.AddPolicy( "Bearer" , new AuthorizationPolicyBuilder()
     .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌​)
     .RequireAuthenticatedUser().Build());
});

这里是添加身份认证服务 。

在Configure方法中添加如下代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
app.UseExceptionHandler(appBuilder =>
{
   appBuilder.Use(async (context, next) =>
   {
     var error = context.Features[ typeof (IExceptionHandlerFeature)] as IExceptionHandlerFeature;
 
     //when authorization has failed, should retrun a json message to client
     if (error != null && error.Error is SecurityTokenExpiredException)
     {
       context.Response.StatusCode = 401;
       context.Response.ContentType = "application/json" ;
 
       await context.Response.WriteAsync(JsonConvert.SerializeObject( new RequestResult
       {
         State = RequestState.NotAuth,
         Msg = "token expired"
       }));
     }
     //when orther error, retrun a error message json to client
     else if (error != null && error.Error != null )
     {
       context.Response.StatusCode = 500;
       context.Response.ContentType = "application/json" ;
       await context.Response.WriteAsync(JsonConvert.SerializeObject( new RequestResult
       {
         State = RequestState.Failed,
         Msg = error.Error.Message
       }));
     }
     //when no error, do next.
     else await next();
   });
});

本段是Handle当身份认证失败时抛出的异常,并返回合适的json 。

在相同的方法中添加另外一段代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
app.UseJwtBearerAuthentication( new JwtBearerOptions()
{
   TokenValidationParameters = new TokenValidationParameters()
   {
     IssuerSigningKey = TokenAuthOption.Key,
     ValidAudience = TokenAuthOption.Audience,
     ValidIssuer = TokenAuthOption.Issuer,
     // When receiving a token, check that we've signed it.
     ValidateIssuerSigningKey = true ,
     // When receiving a token, check that it is still valid.
     ValidateLifetime = true ,
     // This defines the maximum allowable clock skew - i.e. provides a tolerance on the token expiry time
     // when validating the lifetime. As we're creating the tokens locally and validating them on the same
      // machines which should have synchronised time, this can be set to zero. Where external tokens are
     // used, some leeway here could be useful.
     ClockSkew = TimeSpan.FromMinutes(0)
   }
});

本段代码是应用JWTBearerAuthentication身份认证.

4.1.3.TokenAuthController.cs 。

在Controllers中新建一个Web API Controller Class,命名为TokenAuthController.cs。我们将在这里完成登录授权, 。

在同文件下添加两个类,分别用来模拟用户模型,以及用户存储,代码应该是这样

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class User
{
   public Guid ID { get ; set ; }
   public string Username { get ; set ; }
   public string Password { get ; set ; }
}
 
public static class UserStorage
{
   public static List<User> Users { get ; set ; } = new List<User> {
     new User {ID=Guid.NewGuid(),Username= "user1" ,Password = "user1psd" },
     new User {ID=Guid.NewGuid(),Username= "user2" ,Password = "user2psd" },
     new User {ID=Guid.NewGuid(),Username= "user3" ,Password = "user3psd" }
   };
}

接下来在TokenAuthController.cs中添加如下方法 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private string GenerateToken(User user, DateTime expires)
{
   var handler = new JwtSecurityTokenHandler();
  
   ClaimsIdentity identity = new ClaimsIdentity(
     new GenericIdentity(user.Username, "TokenAuth" ),
     new [] {
       new Claim( "ID" , user.ID.ToString())
     }
   );
 
   var securityToken = handler.CreateToken( new SecurityTokenDescriptor
   {
     Issuer = TokenAuthOption.Issuer,
     Audience = TokenAuthOption.Audience,
     SigningCredentials = TokenAuthOption.SigningCredentials,
     Subject = identity,
     Expires = expires
   });
   return handler.WriteToken(securityToken);
}

该方法仅仅只是生成一个Auth Token,接下来我们来添加另外一个方法来调用它 。

在相同文件中添加如下代码 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[HttpPost]
public string GetAuthToken(User user)
{
   var existUser = UserStorage.Users.FirstOrDefault(u => u.Username == user.Username && u.Password == user.Password);
 
   if (existUser != null )
   {
     var requestAt = DateTime.Now;
     var expiresIn = requestAt + TokenAuthOption.ExpiresSpan;
     var token = GenerateToken(existUser, expiresIn);
 
     return JsonConvert.SerializeObject( new {
       stateCode = 1,
       requertAt = requestAt,
       expiresIn = TokenAuthOption.ExpiresSpan.TotalSeconds,
       accessToken = token
     });
   }
   else
   {
     return JsonConvert.SerializeObject( new { stateCode = -1, errors = "Username or password is invalid" });
   }
}

接下来我们来完成授权部分,在相同的文件中添加如下代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public string GetUserInfo()
{
   var claimsIdentity = User.Identity as ClaimsIdentity;
 
   return JsonConvert.SerializeObject( new RequestResult
   {
     State = RequestState.Success,
     Data = new
     {
       UserName = claimsIdentity.Name
     }
   });
}

为方法添加装饰属性 。

[HttpGet] 。

[Authorize("Bearer")] 。

第二行代码说明这个action需要身份验证.

该文件完整的代码应该是这个样子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
using System;
using System.Collections.Generic;
using System.Linq; using Microsoft.AspNetCore.Mvc;
using CSAuthorAngular2InASPNetCore.Auth;
using System.IdentityModel.Tokens.Jwt;
using Newtonsoft.Json;
using System.Security.Claims;
using System.Security.Principal;
using Microsoft.IdentityModel.Tokens;
using CSAuthorAngular2InASPNetCore.Model;
using Microsoft.AspNetCore.Authorization;
 
 
namespace CSAuthorAngular2InASPNetCore.Controllers
{
   [Route( "api/[controller]" )]
   public class TokenAuthController : Controller
   {
     [HttpPost]
     public string GetAuthToken([FromBody]User user)
     {
       var existUser = UserStorage.Users.FirstOrDefault(u => u.Username == user.Username && u.Password == user.Password);
 
       if (existUser != null )
       {
         var requestAt = DateTime.Now;
         var expiresIn = requestAt + TokenAuthOption.ExpiresSpan;
         var token = GenerateToken(existUser, expiresIn);
 
         return JsonConvert.SerializeObject( new RequestResult
         {
           State = RequestState.Success,
           Data = new
           {
             requertAt = requestAt,
             expiresIn = TokenAuthOption.ExpiresSpan.TotalSeconds,
             tokeyType = TokenAuthOption.TokenType,
             accessToken = token
           }
         });
       }
       else
       {
         return JsonConvert.SerializeObject( new RequestResult
         {
           State = RequestState.Failed,
           Msg = "Username or password is invalid"
         });
       }
     }
 
     private string GenerateToken(User user, DateTime expires)
     {
       var handler = new JwtSecurityTokenHandler();
 
       ClaimsIdentity identity = new ClaimsIdentity(
         new GenericIdentity(user.Username, "TokenAuth" ),
         new [] {
           new Claim( "ID" , user.ID.ToString())
         }
       );
 
       var securityToken = handler.CreateToken( new SecurityTokenDescriptor
       {
         Issuer = TokenAuthOption.Issuer,
         Audience = TokenAuthOption.Audience,
         SigningCredentials = TokenAuthOption.SigningCredentials,
         Subject = identity,
         Expires = expires
       });
       return handler.WriteToken(securityToken);
     }
 
     [HttpGet]
     [Authorize( "Bearer" )]
     public string GetUserInfo()
     {
       var claimsIdentity = User.Identity as ClaimsIdentity;
 
       return JsonConvert.SerializeObject( new RequestResult
       {
         State = RequestState.Success,
         Data = new
         {
           UserName = claimsIdentity.Name
         }
       });
     }
   }
 
   public class User
   {
     public Guid ID { get ; set ; }
 
     public string Username { get ; set ; }
 
     public string Password { get ; set ; }
   }
 
   public static class UserStorage
   {
     public static List<User> Users { get ; set ; } = new List<User> {
       new User {ID=Guid.NewGuid(),Username= "user1" ,Password = "user1psd" },
       new User {ID=Guid.NewGuid(),Username= "user2" ,Password = "user2psd" },
       new User {ID=Guid.NewGuid(),Username= "user3" ,Password = "user3psd" }
     };
   }
}

4.2Angular2端 。

4.2.1创建View Model 。

在wwwroot/app下创建一个目录:_model, 并添加一个Typescript文件RequestResult.ts,内容应该是这样.

?
1
2
3
4
5
export class RequestResult {
   State: number;
   Msg: string;
   Data: Object;
}

4.2.2创建Service 。

在wwwroot/app下创建一个目录:_services,并添加一个Typescript文件auth.service.ts,内容应该是这样.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import { Injectable } from "@angular/core" ;
import { Headers, Http } from "@angular/http" ;
import "rxjs/add/operator/toPromise" ;
 
import { RequestResult } from "../_model/RequestResult" ;
 
@Injectable()
export class AuthService {
   private tokeyKey = "token" ;
   private token: string;
 
   constructor(
     private http: Http
   ) { }
 
   login(userName: string, password: string): Promise<RequestResult> {
     return this .http.post( "/api/TokenAuth" , { Username: userName, Password: password }).toPromise()
       .then(response => {
         let result = response.json() as RequestResult;
         if (result.State == 1) {
           let json = result.Data as any;
 
           sessionStorage.setItem( "token" , json.accessToken);
         }
         return result;
       })
       . catch ( this .handleError);
   }
 
   checkLogin(): boolean {
     var token = sessionStorage.getItem( this .tokeyKey);
     return token != null ;
   }
 
   getUserInfo(): Promise<RequestResult> {
     return this .authGet( "/api/TokenAuth" );
   }
 
   authPost(url: string, body: any): Promise<RequestResult> {
     let headers = this .initAuthHeaders();
     return this .http.post(url, body, { headers: headers }).toPromise()
       .then(response => response.json() as RequestResult)
       . catch ( this .handleError);
   }
 
   authGet(url): Promise<RequestResult> {
     let headers = this .initAuthHeaders();
     return this .http.get(url, { headers: headers }).toPromise()
       .then(response => response.json() as RequestResult)
       . catch ( this .handleError);
   }
 
   private getLocalToken(): string {
     if (! this .token) {
       this .token = sessionStorage.getItem( this .tokeyKey);
     }
     return this .token;
   }
 
   private initAuthHeaders(): Headers {
     let token = this .getLocalToken();
     if (token == null ) throw "No token" ;
 
     var headers = new Headers();
     headers.append( "Authorization" , "Bearer " + token);
 
     return headers;
   }
 
   private handleError(error: any): Promise<any> {
     console.error( 'An error occurred' , error);
     return Promise.reject(error.message || error);
   }
}

本文件主要用来完成登录以及登录验证工作,之后该service将可以被注入到Component中以便被Component调用.

注:主要的逻辑都应该写到service中 。

4.2.3.创建Component 。

4.2.3.1.在wwwroot/app下创建一个目录home,该目录用来存放HomeComponent,home应拥有如下文件:

•home.component.ts 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import { Component, OnInit } from "@angular/core" ;
 
import { AuthService } from "../_services/auth.service" ;
 
@Component({
   moduleId: module.id,
   selector: "my-home" ,
   templateUrl: "view.html" ,
   styleUrls: [ "style.css" ]
})
export class HomeComponent implements OnInit {
   isLogin = false ;
   userName: string;
  
   constructor(
     private authService: AuthService
   ) { }
 
   ngOnInit(): void {
     this .isLogin = this .authService.checkLogin();
     if ( this .isLogin) {
       this .authService.getUserInfo().then(res => {
         this .userName = (res.Data as any).UserName;
       });
     }
 
   }
}

查阅代码,在@Component中指定了View以及style.

AuthService被在构造方法中被注入了本Component,ngOnInit是接口OnInit的一个方法,他在Component初始化时会被调用.

•style.css 。

?
1
/*styles of this view*/

本例中没有添加任何样式,如有需要可以写在这里.

•view.html 。

?
1
2
3
4
5
6
7
8
< div * ngIf = "isLogin" >
   < h1 >Hi < span >{{userName}}</ span ></ h1 >
</ div >
 
< div * ngIf = "!isLogin" >
   < h1 >please login</ h1 >
   < a routerLink = "/login" >Login</ a >
</ div >

*ngIf=""是Angular2 的其中一种标记语法,作用是当返回真时渲染该节点,完整教程请参阅官方文档.

4.2.3.2.在wwwroot/app下创建目录Login,该目录用来存放LoginComponent,文件结构类似于上一节.

•login.component.ts 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { Component } from "@angular/core" ;
import { Router } from '@angular/router' ;
 
import { AuthService } from "../_services/auth.service" ;
 
@Component({
   moduleId: module.id,
   selector: "my-login" ,
   templateUrl: "view.html" ,
   styleUrls: [ "style.css" ]
})
export class LoginComponent {
 
   private userName: string;
   private password: string;
 
   constructor(
     private authService: AuthService,
     private router: Router
   ) { }
 
   login() {
     this .authService.login( this .userName, this .password)
       .then(result => {
         if (result.State == 1) {
           this .router.navigate([ "./home" ]);
         }
         else {
           alert(result.Msg);
         }
       });
   }
}

•style.css 。

?
1
/*styles of this view*/

•view.html 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
< table >
   < tr >
     < td >userName:</ td >
     < td >< input [(ngModel)]="userName" placeholder = "useName:try type user1" /></ td >
   </ tr >
   < tr >
     < td >userName:</ td >
     < td >< input [(ngModel)]="password" placeholder = "password:try type user1psd" /></ td >
   </ tr >
   < tr >
     < td ></ td >
     < td >< input type = "button" (click)="login()" value = "Login" /></ td >
   </ tr >
</ table >

4.2.4.应用路由 。

路由是切换多页面用的.

在wwwroot/app下新建一个Typescript文件,命名为app-routing.module.ts,内容应该是这个样子.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import { NgModule } from "@angular/core" ;
import { RouterModule, Routes } from "@angular/router" ;
 
import { HomeComponent } from "./home/home.component" ;
import { LoginComponent } from "./login/login.component"
 
const routes: Routes = [
   { path: "" , redirectTo: "/home" , pathMatch: "full" },
   { path: "home" , component: HomeComponent },
   { path: "login" , component: LoginComponent }
];
 
@NgModule({
   imports: [RouterModule.forRoot(routes)],
   exports: [RouterModule]
})
export class AppRoutingModule { }

接下来我们来应用这个路由, 。

打开app.module.ts,更新代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import { NgModule } from "@angular/core" ;
import { BrowserModule } from "@angular/platform-browser" ;
import { HttpModule } from "@angular/http" ;
import { FormsModule } from "@angular/forms" ;
 
import { AppRoutingModule } from "./app-routing.module" ;
 
import { AuthService } from "./_services/auth.service" ;
 
import { AppComponent } from "./app.component" ;
import { HomeComponent } from "./home/home.component" ;
import { LoginComponent } from "./login/login.component" ;
 
@NgModule({
   bootstrap: [AppComponent],
   imports: [
     BrowserModule,
     HttpModule,
     AppRoutingModule,
     FormsModule
   ],
   declarations: [
     AppComponent,
     HomeComponent,
     LoginComponent
   ],
   providers: [AuthService]
})
export class AppModule { }

NgModule和BrowserModule你可以理解为基础模块,必加的.

HttpModule是做http请求用的.

FormsModule是做双向数据绑定用的,比如下面这样的,如果想把数据从view更新到component,就必须加这个.

?
1
< input [(ngModel)]="userName" placeholder = "useName:try type user1" />

AppRoutingModule即为我们刚才添加的路由文件.

AuthService是我们最早添加的service文件.

AppComponent是我们最初添加的那个app.component.ts里的那个component. 。

HomeComponent,LoginComponent同上.

最后我们再app.component.ts中添加路由锚点, 。

把template的值为 "<router-outlet></router-outlet>" 。

完整的代码应该是这样:

?
1
2
3
4
5
6
7
8
9
import { Component } from '@angular/core' ;
 
@Component({
   moduleId: module.id,
   selector: 'my-app' ,
   template: "<router-outlet></router-outlet>" ,
})
export class AppComponent {
}

router-outlet是路由锚点的关键词.

至此,所有代码完成,F5调试吧.

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.

原文链接:http://www.cnblogs.com/onecodeonescript/p/6062203.html 。

最后此篇关于详解在ASP.NET Core中使用Angular2以及与Angular2的Token base身份认证的文章就讲到这里了,如果你想了解更多关于详解在ASP.NET Core中使用Angular2以及与Angular2的Token base身份认证的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com