跳转到主要内容

标签(标签)

资源精选(342) Go开发(108) Go语言(103) Go(99) angular(82) LLM(75) 大语言模型(63) 人工智能(53) 前端开发(50) LangChain(43) golang(43) 机器学习(39) Go工程师(38) Go程序员(38) Go开发者(36) React(33) Go基础(29) Python(24) Vue(22) Web开发(20) Web技术(19) 精选资源(19) 深度学习(19) Java(18) ChatGTP(17) Cookie(16) android(16) 前端框架(13) JavaScript(13) Next.js(12) 安卓(11) 聊天机器人(10) typescript(10) 资料精选(10) NLP(10) 第三方Cookie(9) Redwoodjs(9) LLMOps(9) Go语言中级开发(9) 自然语言处理(9) PostgreSQL(9) 区块链(9) mlops(9) 安全(9) 全栈开发(8) ChatGPT(8) OpenAI(8) Linux(8) AI(8) GraphQL(8) iOS(8) 软件架构(7) Go语言高级开发(7) AWS(7) C++(7) 数据科学(7) whisper(6) Prisma(6) 隐私保护(6) RAG(6) JSON(6) DevOps(6) 数据可视化(6) wasm(6) 计算机视觉(6) 算法(6) Rust(6) 微服务(6) 隐私沙盒(5) FedCM(5) 语音识别(5) Angular开发(5) 快速应用开发(5) 提示工程(5) Agent(5) LLaMA(5) 低代码开发(5) Go测试(5) gorm(5) REST API(5) 推荐系统(5) WebAssembly(5) GameDev(5) CMS(5) CSS(5) machine-learning(5) 机器人(5) 游戏开发(5) Blockchain(5) Web安全(5) Kotlin(5) 低代码平台(5) 机器学习资源(5) Go资源(5) Nodejs(5) PHP(5) Swift(5) 智能体(4) devin(4) Blitz(4) javascript框架(4) Redwood(4) GDPR(4) 生成式人工智能(4) Angular16(4) Alpaca(4) 编程语言(4) SAML(4) JWT(4) JSON处理(4) Go并发(4) kafka(4) 移动开发(4) 移动应用(4) security(4) 隐私(4) spring-boot(4) 物联网(4) nextjs(4) 网络安全(4) API(4) Ruby(4) 信息安全(4) flutter(4) 专家智能体(3) Chrome(3) CHIPS(3) 3PC(3) SSE(3) 人工智能软件工程师(3) LLM Agent(3) Remix(3) Ubuntu(3) GPT4All(3) 软件开发(3) 问答系统(3) 开发工具(3) 最佳实践(3) RxJS(3) SSR(3) Node.js(3) Dolly(3) 移动应用开发(3) 低代码(3) IAM(3) Web框架(3) CORS(3) 基准测试(3) Go语言数据库开发(3) Oauth2(3) 并发(3) 主题(3) Theme(3) earth(3) nginx(3) 软件工程(3) azure(3) keycloak(3) 生产力工具(3) gpt3(3) 工作流(3) C(3) jupyter(3) 认证(3) prometheus(3) GAN(3) Spring(3) 逆向工程(3) 应用安全(3) Docker(3) Django(3) R(3) .NET(3) 大数据(3) Hacking(3) 渗透测试(3) C++资源(3) Mac(3) 微信小程序(3) Python资源(3) JHipster(3) 大型语言模型(2) 语言模型(2) 可穿戴设备(2) JDK(2) SQL(2) Apache(2) Hashicorp Vault(2) Spring Cloud Vault(2) Go语言Web开发(2) Go测试工程师(2) WebSocket(2) 容器化(2) AES(2) 加密(2) 输入验证(2) ORM(2) Fiber(2) Postgres(2) Gorilla Mux(2) Go数据库开发(2) 模块(2) 泛型(2) 指针(2) HTTP(2) PostgreSQL开发(2) Vault(2) K8s(2) Spring boot(2) R语言(2) 深度学习资源(2) 半监督学习(2) semi-supervised-learning(2) architecture(2) 普罗米修斯(2) 嵌入模型(2) productivity(2) 编码(2) Qt(2) 前端(2) Rust语言(2) NeRF(2) 神经辐射场(2) 元宇宙(2) CPP(2) 数据分析(2) spark(2) 流处理(2) Ionic(2) 人体姿势估计(2) human-pose-estimation(2) 视频处理(2) deep-learning(2) kotlin语言(2) kotlin开发(2) burp(2) Chatbot(2) npm(2) quantum(2) OCR(2) 游戏(2) game(2) 内容管理系统(2) MySQL(2) python-books(2) pentest(2) opengl(2) IDE(2) 漏洞赏金(2) Web(2) 知识图谱(2) PyTorch(2) 数据库(2) reverse-engineering(2) 数据工程(2) swift开发(2) rest(2) robotics(2) ios-animation(2) 知识蒸馏(2) 安卓开发(2) nestjs(2) solidity(2) 爬虫(2) 面试(2) 容器(2) C++精选(2) 人工智能资源(2) Machine Learning(2) 备忘单(2) 编程书籍(2) angular资源(2) 速查表(2) cheatsheets(2) SecOps(2) mlops资源(2) R资源(2) DDD(2) 架构设计模式(2) 量化(2) Hacking资源(2) 强化学习(2) flask(2) 设计(2) 性能(2) Sysadmin(2) 系统管理员(2) Java资源(2) 机器学习精选(2) android资源(2) android-UI(2) Mac资源(2) iOS资源(2) Vue资源(2) flutter资源(2) JavaScript精选(2) JavaScript资源(2) Rust开发(2) deeplearning(2) RAD(2)

大家好!

在本文中,我将讨论 ADFS + Angular + ASP.NET Core API。

我需要一起做这三件事,我很难找到关于这样做的内容。当它有关于 Angular 的信息时,它没有关于 ASP.NET Core API 的信息,或者它是关于 ASP.NET MVC 项目的信息。哦,很难过!

但是现在,我将这三件事结合在一起,我想解释一些我学到的东西,并提供一个可以帮助其他人的项目。

那么,让我们开始吧!

第 1 部分:ADFS


我不会专注于在 ADFS 中配置您的应用程序,我认为您可以在 Internet 上找到足够多的相关内容。

但是,你需要知道一些事情:

由于前端将与您的后端解耦,因此您需要使用 JWT + OAUTH/OIDC 的方法,您将在其中获得访问令牌。因此,基本上“身份验证发生”在前端后端检查请求是否有效,或者换句话说,请求的标头中是否有有效的访问令牌

这称为隐式流(Implicit Flow),根据我当时的研究,从 ADFS 4 开始就允许这样做。

除此之外,最好记住,因为它是一个 SPA 应用程序,它有一种特定的方式可以在 ADFS 上配置它,比如“本机应用程序”或类似的东西。好吧,我想你可以在谷歌上找到它,然后你就会有一个客户 ID 和其他信息。

 

第 02 部分:Angular


我不会专注于创建 Angular 应用程序。我想你知道怎么做。如果没有,请检查以下链接:

https://angular.io/
https://cli.angular.io/

我有一个项目,您可以在其中建立自己的基础:https://github.com/gabrielfbarros/aspnetcore-angular-adfs/tree/master/front。

你可能会想,我并没有把重点放在应用程序的一个伟大的结构上!

为了使与 ADFS 的集成更容易,我寻找了一个可以帮助我的库。我发现的很少,但似乎更常用和更适合我的是“angular-oauth2-oidc”。你可以在这里查看:https://www.npmjs.com/package/angular-oauth2-oidc

在上面的示例中,基本上我通过 CLI 创建了一个 Angular 5 应用程序,并按照 lib 教程中的说明进行操作。我在下面详细说明:

- 您需要在 package.json 文件中添加 lib。看,如果你需要对 Angular < 6(4.3 到 5.x)的支持,你可以下载之前的 3.1.4 版本(npm i angular-oauth2-oidc@^3 --save)。如果你正在使用 Angular 6+,你可以使用最新版本。查看 npm 网站上的教程。

- 在 app.component 中,创建一个构造函数,并在其中从 lib 配置 OAuthService:

public constructor(private oauthService: OAuthService) {
  this.oauthService.redirectUri = window.location.origin;
  this.oauthService.clientId = 'YOUR_CLIENT_ID';
  this.oauthService.loginUrl = 'https://YOUR_SERVER/adfs/oauth2/authorize';
  this.oauthService.issuer = 'https://YOUR_SERVER/adfs';
  this.oauthService.scope = "openid profile";
  this.oauthService.responseType = 'id_token token';
  this.oauthService.setStorage(sessionStorage);
  this.oauthService.tryLogin();
}

您注意到我刚刚将 redirectUri 设置为我的应用程序的基本 url。此配置应使用您在 ADFS 中配置的重定向 url 进行设置,因为在验证用户身份后,ADFS 将重定向到该配置的 url。

clientId 是 ADFS 为您的应用程序生成的。它类似于“指导”值。

loginUrl 是 ADFS 的授权端点的 url。基本上,您需要通过 ADFS 服务器的路径更改“YOUR_SERVER”,在上面的示例中。

issuer 基本上是保存 ADFS 的服务器的 url,仅以“/adfs”结尾,但在我的情况下,此路径与之前的路径 loginUrl 不同。我不知道究竟是为什么。经过大量测试后,我发现您有一个端点可以为您提供其他一些信息:https://YOUR_SERVER/adfs/.well-known/openid-configuration,其中的信息之一是发行者,即我刚刚在我的 Angular 配置中使用过。

好吧,这基本上就是我需要的所有配置,以使 lib “看到”我的 ADFS。

- 在 app.module 中,您需要在导入声明中导入“OAuthModule.forRoot()”。

- 在我的示例中,我创建了一个 home.component,它有一个向 API 发送 GET 请求的按钮,并且 API 由安全策略保护。因此,我创建了 my.service,其中创建了以下函数:

getPrivateMessage(): Observable<string> {
  let options = this.getAuthHeader();
  
  return this.http.get(this.UrlService + "home/private", options)
    .map((res: Response) => <string>super.extractData(res))
    .catch(err => super.serviceError(err, true));
}

查看“this.getAuthHeader()”调用。 您可以检查 my.service 是否扩展了我创建该函数的 base.service:

protected getAuthHeader(): RequestOptions {
  this.Token = this.oauthService.getAccessToken();
  
  let headers = new Headers({ 'Content-Type': 'application/json' });
  headers.append('Authorization', `Bearer ${this.Token}`);
  
  let options = new RequestOptions({ headers: headers });
  return options;
}

好吧,这就是魔法发生的地方! 在这里,我使用“this.oauthService.getAccessToken()”来获取访问令牌,并将其作为 Authorization Bearer 属性放在标头中。

- 除此之外,我创建了一个 app.routes 和一个 auth-guard.service。 在警卫服务中,我检查会话存储中是否存在有效的访问令牌。 如果没有或者如果用户登录失败,它将启动隐式流程,这将打开 ADFS 的登录页面:

canActivate(routeAc: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
 
  if (!this.oauthService.hasValidAccessToken()) {
    this.oauthService.tryLogin();
  }

  if (!this.oauthService.hasValidAccessToken()) {
    this.oauthService.initImplicitFlow();
    return false;
  }

  return true;
}

所以在我的路由中使用这个守卫,我保证用户已经过身份验证:

{ path: ‘home’, component: HomeComponent, canActivate: [AuthGuardService] }

- 最后但同样重要的是,在我的 home.component 中有一个注销功能:

logout(){
 this.oauthService.logOut();
 window.location.href= 'https://YOUR_SERVER/adfs/ls/?wa=wsignoutcleanup1.0';
 }

好吧,你可以看到它很简单,但只有在你知道这一切之后!

在主页上,登录后,您将看到 ADFS 生成的访问令牌,该令牌将发送到 API。您可以在 https://jwt.io/ 中查看,查看 ADFS 向您返回了哪些信息。就我而言,我们能够从 ADFS 获取应用程序的几个重要信息。

第 3 部分:ASP.NET Core API


对于后端,我还有一个项目,您可以在其中建立自己的基础:https://github.com/gabrielfbarros/aspnetcore-angular-adfs/tree/master/back。

你也可以想象我并没有把重点放在应用程序的一个很好的结构上!

在上面的示例中,基本上我从 Visual Studio 的模板创建了一个 ASP.NET Core 2.0 API。

主要配置发生在 Startup.cs 类中。正如我之前提到的,API 将接收请求,并且对于每个请求,它需要检查是否提供了有效的访问令牌,否则 API 应该返回代码 401(未授权)。

为了确保任何请求都会检查访问令牌,您需要向 MVC 管道添加一个过滤器。在 ConfigureServices 方法中:

services.AddMvc(options =>
{
  var policy = new AuthorizationPolicyBuilder()
    .AddAuthenticationSchemes("Bearer")
    .RequireAuthenticatedUser()
    .Build();
    
  options.Filters.Add(new AuthorizeFilter(policy));
});

看我为我的身份验证方案定义了一个名称:“Bearer”。 现在我们需要将身份验证配置为 JWT。 仍然在 ConfigureServices 方法中:

services.AddAuthentication("Bearer")
  .AddJwtBearer(options =>
  {
    options.Authority = "https://YOUR_SERVER/adfs";
    options.Audience = "microsoft:identityserver:YOUR_CLIENT_ID";
    options.TokenValidationParameters = new TokenValidationParameters()
    {
      ValidIssuer = "http://YOUR_SERVER/adfs/services/trust"
    };
    
    options.Events = new JwtBearerEvents
    {
      OnTokenValidated = async ctx =>
      {
        var claims = new List<Claim>
        {
          new Claim("GivenType", "GivenValue")
        };
        
        ctx.Principal.AddIdentity(new ClaimsIdentity(claims));
      }
    };
  });

您会看到,权威是 Angular 应用程序的发行者。

Audience 是我的致命弱点! 我花了一些时间来找出我应该在这里使用哪些信息。 您会注意到该值具有“microsoft:identityserver:”和客户端 ID。 好吧,我从访问令牌中获得了这些信息,在 https://jwt.io/ 中查看。 它是令牌中的“aud”值。

ValidIssuer 是 ADFS 的服务/信任端点。

在 Events 属性中,您可以配置 OnTokenValidated 并向身份添加声明,或者您可以在验证令牌后执行任何其他必要的操作。

并且不是强制性的,但非常有用的是配置策略,这是 ASP.NET Core 的一个新特性:

services.AddAuthorization(options =>
{
  options.AddPolicy("Given Policy", policy => policy.RequireClaim("GivenType", "GivenValue"));
});

在这里,我们创建一个策略并说明满足该策略所必需的声明。 看看声明与我在上面的 OnTokenValidated 中添加给用户的声明相同,因此用户将有权访问该策略。

并且为了使策略有意义,我们可以在 Controller 中使用它:

[Authorize(Policy = “Given Policy”)]
public class HomeController : Controller

因此,通过所有这些配置,任何请求,对于任何控制器,它都会检查您的 ADFS,如果标头中有有效的访问令牌。 特别是对于这个 HomeController,它会检查用户是否遵守我们创建的策略。

就是这样! 现在看起来并不难,但我花了一些时间看一些东西。

如果您对这种技术组合有其他方法,请告诉我们,留下您的笔记!

我希望我能帮助你!

再见!

文章链接