您可以采取以下措施来确保您的 Angular SPA 和 asp.net core web api 安全。
技术解决方案
1) 实现Web application to web API authentication scenario。
2) 使用https://portal.azure.com 配置认证过程。
3) Use adal-angular4(版本 3.0.1+)Angular 包,用于在 Angular 应用程序中实现身份验证。
4) 使用 Microsoft.AspNetCore.Authentication.AzureAD.UI NuGet 包实现对 Asp.Net 核心 Web API 服务的身份验证。
先决条件
注册 Angular 应用程序
从https://portal.azure.com 在 Azure Active Directory 中注册应用程序
转到“Azure Active Directory”->“应用注册”并选择添加“新应用注册”。
注册 Web API
从https://portal.azure.com 在 Azure Active Directory 中注册 Web API 服务。
注册过程类似于注册 Angular 应用程序。 (见上文)
配置对 Web API 资源的访问
客户端应用程序通过声明权限请求来获得对资源服务器的访问权限。
转到 Azure Active Directory -> 应用注册并选择 Angular 应用程序的设置。
选择 Angular 应用程序访问的 Web API:
使用委派权限启用访问
在注册的 Angular 应用程序清单中添加所需的资源(Web API)访问权限:
授予对 Web API 资源的访问权限
安装adal包
安装 adal 包 adal-angular4(版本 3.0.1+)。包 adal-angular4 已更新为与 angular6 兼容。发现正确的包是令人困惑的,因为包名称是指 angular 4,而且还有另一个包 adal-angular5 与 angular 6 不兼容。
技术解决方案
认证过程
第一步:
当用户第一次通过浏览器访问应用程序时,Angular 应用程序检测到它没有经过身份验证并重定向到 Microsoft 登录以进行凭据介绍。
第 2 步:
在登录步骤之后,身份验证服务将流程重定向到配置的 Angular 应用程序回调,在此完成身份验证流程。
第 3 步:
Angular 应用程序调用所需的 Web API。身份验证令牌在调用 Web API 之前添加到 HTTP 标头中。
第 4 步:
Web API 验证身份验证令牌,并在成功的情况下返回请求的资源。
实施
第 1 步:
a) 配置 ADAL 服务
import { Component } from '@angular/core';
import { AdalService } from 'adal-angular4';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
private adalConfig = {
tenant: '[TENANT_GUID]',
clientId: '[CLIENTID_GUID]',
redirectUri: "[LOGIN_REDIRECT_URL]",
postLogoutRedirectUri: "[POST_LOGOUT_REDIRECT_URL]",
endpoints: {
"[HOME_URL_WEB_API]": "[HOME_WEB_API_GUID]"
}
}
constructor(private adal: AdalService) {
this.adal.init(this.adalConfig);
}
signOut(): void {
this.adal.logOut();
}
}
[TENANT_GUID] 是 Azure AD 目录 ID。
b) 实现一个防护,在出现未经身份验证的请求时重定向到登录
import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
import { AdalService } from 'adal-angular4';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private adal: AdalService) { }
canActivate(): boolean {
if (this.adal.userInfo.authenticated) {
return true;
}
this.adal.login();
return false;
}
}
c) 保护路由器类中的应用路径:
const routes: Routes = [
{ path: '', component: MyComponent, canActivate: [AuthGuard] },
{ path: 'auth-callback', component: AuthCallbackComponent },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
第 2 步:- 完成登录过程。
实现一个回调组件,该组件将作为登录过程的一部分被调用。
回调 URL 的注册在步骤 1 中使用 redirectUri 信息配置 adal 时完成。
import { Component, OnInit, NgZone } from '@angular/core';
import { Router } from '@angular/router';
import { AdalService } from 'adal-angular4';
@Component({
selector: 'app-auth-callback',
templateUrl: './auth-callback.component.html',
styleUrls: ['./auth-callback.component.css']
})
export class AuthCallbackComponent implements OnInit {
constructor(private router: Router, private adal: AdalService, private _zone: NgZone) { }
ngOnInit() {
this.adal.handleWindowCallback();
setTimeout(() = {
this._zone.run(
() = this.router.navigate(['/'])
);
}, 200);
}
}
handleWindowCallback() 将身份验证令牌添加到会话。
第 3 步:
为发送到 Web API 的 HTTP 请求设置身份验证令牌
Adal 使它成为一个简单的步骤。唯一要做的步骤是在 app.module.ts 文件中注册开箱即用的 AdalInterceptor:
从 '@angular/platform-browser' 导入 { BrowserModule };
从'@angular/core'导入{ NgModule };
从“@angular/common/http”导入 { HttpClientModule };
从“@angular/forms”导入 { FormsModule };
import { AppComponent } from './app.component';
import { AppRoutingModule } from './/app-routing.module';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { AuthCallbackComponent } from './auth-callback/auth-callback.component';
import { AdalService, AdalInterceptor } from 'adal-angular4';
@NgModule({
declarations: [
AppComponent,
AuthCallbackComponent
],
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule,
FormsModule
],
providers: [AdalService, { provide: HTTP_INTERCEPTORS, useClass: AdalInterceptor, multi: true }],
bootstrap: [AppComponent]
})
export class AppModule { }
第 4 步:
在 Web API 服务中验证身份验证令牌
在 Web API Startup.cs 文件中将身份验证服务配置为 AzureADBear:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)
.AddAzureADBearer(options => Configuration.Bind("AzureAd", options));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddCors(options =
{
options.AddPolicy("AllowAllOrigins",
builder =
{
builder.AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();
});
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseCors("AllowAllOrigins");
app.UseAuthentication();
app.UseStaticFiles();
app.UseMvc(routes =
{
routes.MapRoute(name: "default", template: "api/{controller}/{id}");
});
}
请确保您已安装先决条件部分中提到的 Microsoft.AspNetCore.Authentication.AzureAD.UI NuGet 包。
在 appsettings.json 中添加 AzureAD 部分,以便为验证过程提供身份验证详细信息:
"AzureAd": {
"Instance": "https://login.microsoftonline.com",
"Domain": "[AD_DOMAIN]",
"TenantId": "[TENANTID_GUID]",
"ClientId": "[CLIENTID_GUID]"
}
将上述占位符替换为以下信息:
[AD_DOMAIN] 是 Azure AD 域。
[TENANT_GUID] 是 Azure AD 目录 ID。 (见上文)
[CLIENTID_GUID] 是 Web API 的应用程序 ID。
最后用 filter 属性装饰你的控制器,如下所示:
[Authorize]
[ApiController]
public class MyController : ControllerBase
希望对你有帮助。