如何将 Saml 身份验证添加到 ASP.NET Web API 应用程序

Min*_*ity 5 asp.net-web-api azure-active-directory angular

我有一个带有 asp.net Web Api 后端和 Angular 前端的 Web 应用程序。该应用程序使用基于表单的身份验证来根据其数据库检查用户的身份。

我的任务是使用 Azure AD 作为我的身份提供商,将 Saml 身份验证添加到应用程序中。

我已经尝试使用 SustainSys: 将 SAML 身份验证添加到 .net WebAPI

我使用这种方法的问题是,Angular SPA 不是由 Saml 身份验证的最终重定向触发的,因此不执行登录操作。

我正在评估的另一个选择是 Adal: https: //www.npmjs.com/package/microsoft-adal-angular6

在这种情况下,我不知道应该在 Web API 中实现什么来执行身份验证。

添加此类身份验证的正确方法是什么?

Moh*_*rma 4

您可以采取以下措施来确保 Angular SPA 和 asp.net core Web api 的安全。

\n\n

技术方案

\n\n

1) 实现Web应用程序到Web API的身份验证场景

\n\n

2) 使用https://portal.azure.com配置身份验证过程。

\n\n

3)使用 adal-angular4(版本 3.0.1+)Angular 包在 Angular 应用程序中实现身份验证。

\n\n

4) 使用 Microsoft.AspNetCore.Authentication.AzureAD.UI NuGet 包对 Asp.Net core Web API 服务实施身份验证。

\n\n

先决条件

\n\n

注册 Angular 应用程序

\n\n

从https://portal.azure.com在 Azure Active Directory 中注册应用程序\n转至 \xe2\x80\x9cAzure Active Directory\xe2\x80\x9d -> \xe2\x80\x9cApp Registrations\xe2\x80\x9d 并选择添加\xe2\x80\x9c新应用程序注册\xe2\x80\x9d。

\n\n

在此输入图像描述

\n\n

注册网络API

\n\n

从https://portal.azure.com注册 Azure Active Directory 中的 Web API 服务。\n注册过程与注册 Angular 应用程序类似。(往上看)

\n\n

配置对 Web API 资源的访问

\n\n

客户端应用程序通过声明权限请求来获取对资源服务器的访问权限。\n转到 Azure Active Directory -> 应用注册,然后选择 Angular 应用程序的设置。

\n\n

选择 Angular 应用程序访问的 Web API:

\n\n

在此输入图像描述

\n\n

通过委派权限启用访问

\n\n

在此输入图像描述

\n\n

所需的资源(Web API)访问权限已添加到注册的 Angular 应用程序清单中:

\n\n

在此输入图像描述

\n\n

授予对 Web API 资源的访问权限

\n\n

在此输入图像描述

\n\n

安装adal包

\n\n

安装 adal 包 adal-angular4(版本 3.0.1+)。软件包 adal-angular4 已更新以与 angular6 兼容。找到正确的包很令人困惑,因为包名称指的是 Angular 4,而且还有另一个包 Adal-Angular5 与 Angular 6 不兼容。

\n\n

技术方案

\n\n

认证流程

\n\n

第一步:

\n\n

当用户第一次通过浏览器访问应用程序时,角度应用程序检测到它未经身份验证,并重定向到 Microsoft 登录以进行凭据介绍。

\n\n

在此输入图像描述

\n\n

第2步:

\n\n

登录步骤之后,身份验证服务将流程重定向到配置的角度应用程序回调,身份验证过程在此完成。

\n\n

步骤3:

\n\n

角度应用程序调用所需的 Web API。在调用 Web API 之前,身份验证令牌会添加到 HTTP 标头中。

\n\n

步骤4:

\n\n

Web API 验证身份验证令牌,如果成功,则返回请求的资源。

\n\n

执行

\n\n

步骤1:

\n\n

a) 配置 ADAL 服务

\n\n
import { Component } from \'@angular/core\';\nimport { AdalService } from \'adal-angular4\';\n\n@Component({\n  selector: \'app-root\',\n  templateUrl: \'./app.component.html\',\n  styleUrls: [\'./app.component.css\']\n})\nexport class AppComponent {\n  title = \'app\';\n\n  private adalConfig = {\n    tenant: \'[TENANT_GUID]\',\n    clientId: \'[CLIENTID_GUID]\',\n    redirectUri: "[LOGIN_REDIRECT_URL]",\n    postLogoutRedirectUri: "[POST_LOGOUT_REDIRECT_URL]",\n    endpoints: {\n      "[HOME_URL_WEB_API]": "[HOME_WEB_API_GUID]"\n    }\n  }\n\n  constructor(private adal: AdalService) {\n    this.adal.init(this.adalConfig);\n  }\n\n  signOut(): void {\n    this.adal.logOut();\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

[TENANT_GUID] 是 Azure AD 目录 ID。

\n\n

在此输入图像描述

\n\n

b) 实现一个防护,在出现未经身份验证的请求时重定向到登录

\n\n
import { Injectable } from \'@angular/core\';\nimport { CanActivate } from \'@angular/router\';\nimport { AdalService } from \'adal-angular4\';\n\n@Injectable({\n  providedIn: \'root\'\n})\nexport class AuthGuard implements CanActivate {\n\n  constructor(private adal: AdalService) { }\n\n  canActivate(): boolean {\n\n    if (this.adal.userInfo.authenticated) {\n      return true;\n    }\n\n    this.adal.login();\n\n    return false;\n  }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

c) 保护路由器类中的应用程序路径:

\n\n
const routes: Routes = [\n  { path: \'\', component: MyComponent, canActivate: [AuthGuard] },\n  { path: \'auth-callback\', component: AuthCallbackComponent },\n];\n\n@NgModule({\n  imports: [RouterModule.forRoot(routes)],\n  exports: [RouterModule]\n})\nexport class AppRoutingModule {}\n
Run Code Online (Sandbox Code Playgroud)\n\n

第 2 步:- 完成登录过程。

\n\n

实现将在登录过程中调用的回调组件。\n在使用redirectUri 信息配置adal 时,在步骤1 中完成回调URL 的注册。

\n\n
import { Component, OnInit, NgZone } from \'@angular/core\';\nimport { Router } from \'@angular/router\';\nimport { AdalService } from \'adal-angular4\';\n\n@Component({\n  selector: \'app-auth-callback\',\n  templateUrl: \'./auth-callback.component.html\',\n  styleUrls: [\'./auth-callback.component.css\']\n})\nexport class AuthCallbackComponent implements OnInit {\n\n  constructor(private router: Router, private adal: AdalService, private _zone: NgZone) { }\n\n  ngOnInit() {\n    this.adal.handleWindowCallback();\n\n    setTimeout(() = {\n      this._zone.run(\n        () = this.router.navigate([\'/\'])\n      );\n    }, 200);\n  }\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

handleWindowCallback() 将身份验证令牌添加到会话中。

\n\n

步骤3:

\n\n

为发送到 Web API 的 HTTP 请求设置身份验证令牌\nAdal 使这一步变得简单。唯一要做的步骤是在 app.module.ts 文件中注册开箱即用的 AdalInterceptor:

\n\n

从 \'@angular/platform-b​​rowser\' 导入 { BrowserModule };\n从 \'@angular/core\' 导入 { NgModule };\n从 \'@angular/common/http\' 导入 { HttpClientModule };\n导入{ FormsModule } 来自 \'@angular/forms\';

\n\n
import { AppComponent } from \'./app.component\';\nimport { AppRoutingModule } from \'.//app-routing.module\';\nimport { HTTP_INTERCEPTORS } from \'@angular/common/http\';\nimport { AuthCallbackComponent } from \'./auth-callback/auth-callback.component\';\nimport { AdalService, AdalInterceptor } from \'adal-angular4\';\n\n@NgModule({\n  declarations: [\n    AppComponent,\n    AuthCallbackComponent\n  ],\n  imports: [\n    BrowserModule,\n    HttpClientModule,\n    AppRoutingModule,\n    FormsModule\n  ],\n  providers: [AdalService, { provide: HTTP_INTERCEPTORS, useClass: AdalInterceptor, multi: true }],\n  bootstrap: [AppComponent]\n})\nexport class AppModule { }\n
Run Code Online (Sandbox Code Playgroud)\n\n

步骤4:

\n\n

验证 Web API 服务中的身份验证令牌\n在 Web API Startup.cs 文件中将身份验证服务配置为 AzureADBear:

\n\n
public void ConfigureServices(IServiceCollection services)\n{\n\n    services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme)\n    .AddAzureADBearer(options => Configuration.Bind("AzureAd", options));\n\n    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);\n    services.AddCors(options = \n    {\n        options.AddPolicy("AllowAllOrigins",\n         builder =\n         {\n             builder.AllowAnyMethod().AllowAnyHeader().AllowAnyOrigin();\n         });\n    });\n}\npublic void Configure(IApplicationBuilder app, IHostingEnvironment env)\n{\n    if (env.IsDevelopment())\n    {\n        app.UseDeveloperExceptionPage();\n    }\n    else\n    {\n        app.UseHsts();\n    }\n\n    app.UseHttpsRedirection();\n\n    app.UseCors("AllowAllOrigins");\n    app.UseAuthentication();\n\n    app.UseStaticFiles();\n    app.UseMvc(routes =\n    {\n        routes.MapRoute(name: "default", template: "api/{controller}/{id}");\n    });\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

请确保您已安装先决条件部分中提到的 Microsoft.AspNetCore.Authentication.AzureAD.UI NuGet 包。\n在 appsettings.json 中添加 AzureAD 部分,以便为验证过程提供身份验证详细信息:

\n\n
"AzureAd": {\n  "Instance": "https://login.microsoftonline.com",\n  "Domain": "[AD_DOMAIN]",\n  "TenantId": "[TENANTID_GUID]",\n  "ClientId": "[CLIENTID_GUID]"\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

将上述占位符替换为以下信息:

\n\n

[AD_DOMAIN] 是 Azure AD 域。

\n\n

[TENANT_GUID] 是 Azure AD 目录 ID。(往上看)

\n\n

[CLIENTID_GUID] 是 Web API 的应用程序 ID。

\n\n

最后用过滤器属性装饰你的控制器,如下所示:

\n\n
[Authorize]\n[ApiController]\npublic class MyController : ControllerBase\n
Run Code Online (Sandbox Code Playgroud)\n\n

希望能帮助到你。

\n