当前位置: 首页 > news >正文

通过OpenIddict设计一个授权服务器02-创建asp.net项目

在这一部分中,我们将创建一个ASPNET核心项目,作为我们授权服务器的最低设置。我们将使用MVC来提供页面,并将身份验证添加到项目中,包括一个基本的登录表单。

创建一个空的asp.net core项目

正如前一篇文章中所说,授权服务器只是另一个web应用程序。以下内容将指导您使用用户名密码登录来设置ASPNET Core应用程序。我选择不使用ASPNET core 标识来保持简单。基本上,每个用户名密码组合都可以工作。
让我们从创建一个名为AuthorizationServer的新web应用程序开始,使用 ASP.NET Core Empty template

dotnet new web --name AuthorizationServer

在这里插入图片描述
我们将只处理此项目,并且不会在本指南中添加解决方案文件。
OpenIddict要求我们使用https协议,即使在本地开发时也是如此。要确保本地证书是可信的,您必须运行以下命令:

dotnet dev-certs https --trust

在这里插入图片描述

在Windows上,证书将被添加到证书存储中,在OSX上,证书被添加到密钥链中。在Linux上,没有一种跨发行版的标准方式来信任证书。在Hanselman的博客文章中关于这个主题的信息。
启动应用程序以查看是否一切正常

dotnet run --project AuthorizationServer

在这里插入图片描述
访问localhost:5001应该能看到Hello World!
在这里插入图片描述

mvc

我们已经创建了一个基于ASPNET Core Empty模板的项目。这是一个非常小的模板。我这样做是有意的,因为我喜欢在我的项目中尽可能少的“噪音”,以保持事情的清晰和简单。
使用这个模板的缺点是我们必须自己添加MVC。首先,我们需要通过更改Startup.cs类来启用MVC:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
var app = builder.Build();app.UseStaticFiles();app.UseRouting();app.MapDefaultControllerRoute();
app.Run();

MVC是通过调用services.AddControllersWithViews()。端点设置为使用默认布线。我们还启用了静态文件的服务,我们需要它来提供wwwroot文件夹中的样式表。
现在,让我们创建控制器、视图和视图模型。首先在项目文件夹中添加以下文件夹结构(注意大小写):

/Controllers
/Views
/Views/Home  
/Views/Shared
/ViewModels
/wwwroot
/wwwroot/css

在这里插入图片描述

布局

我们添加的第一项是一个名为_layout.cshtml的布局文件,该文件位于Views/Shared文件夹中。该文件定义了应用程序的总体布局,还从CDN加载Bootstrap和jQuery。jQuery是Bootstrap的一个依赖项。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no" /><title>OpenIddict - Authorization Server</title>@* <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" crossorigin="anonymous"> *@<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.3/css/bootstrap.min.css" rel="stylesheet"><link rel="stylesheet" href="~/css/site.css" />
</head>
<body><div class="container-sm mt-3"><div class="row mb-3"><div class="col text-center"><h1>Authorization Server</h1></div></div><div class="row"><div class="col-xs-12 col-md-8 col-xl-4 offset-md-2 offset-xl-4 text-center mb-3">@RenderBody()</div></div></div>@* <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" crossorigin="anonymous"></script> *@@* <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script> *@<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.slim.min.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.3/js/bootstrap.bundle.min.js"></script>
</body>
</html>

为了使布局和视图正常工作,我们需要将两个文件添加到\views文件夹中:
_ViewStart.cshtml

@{Layout = "_Layout";
}

_ViewImports.cshtml

@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

在这里插入图片描述

首页

在/Controllers文件夹中添加一个基本的HomeController,其唯一目的是为我们的主页提供服务:
将Index.chtml添加到Views/Home文件夹,该文件夹由HomeController提供服务:

<h2>MVC is working</h2>

最后但同样重要的是,我们需要一些造型。将名为site.css的样式表添加到wwwroot\css文件夹中:

:focus {outline: 0 !important;
}.input-validation-error {border: 1px solid darkred;
}form {width: 100%;
}.form-control {border: 0;border-radius: 0;border-bottom: 1px solid lightgray;font-size: 0.9rem;
}.form-control:focus {border-bottom-color: lightgray;box-shadow: none;}.form-control.form-control-last {border-bottom: 0;}.form-control::placeholder {opacity: 0.6;}.form-control.input-validation-error {border: 1px solid darkred;}

一些样式规则已经添加到样式表中,预计我们稍后将创建登录表单。
如果您想使用SASS,或使用SASS自定义引导程序,请查看我关于使用ASPNET设置引导程序SASS的文章。
让我们运行应用程序,看看是否一切正常,您应该在浏览器中看到这样的内容:
在这里插入图片描述

启用身份验证

在ASP.NET Core,身份验证由IAuthenticationService处理。身份验证服务使用身份验证处理程序来完成与身份验证相关的操作。
身份验证处理程序在启动期间注册,其配置选项称为“方案(scheme)”。身份验证方案是通过在“startup”中Startup.ConfigureServices来指定的。
或者在这个项目中,我们将使用cookie身份验证,因此我们需要在Startup.cs的ConfigureServices方法中注册cookie身份验证方案:

using Microsoft.AspNetCore.Authentication.Cookies;var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>{options.LoginPath = "/account/login";});
var app = builder.Build();app.UseStaticFiles();app.UseRouting();app.MapDefaultControllerRoute();
app.Run();

登录路径设置为/account/login,我们将很快实现此端点。
通过调用应用程序的 IApplicationBuilder 上的 UseAuthentication 扩展方法来添加使用注册的身份验证方案的身份验证中间件:

app.UseRouting();
app.UseAuthentication();//需要放在UseRouting和MapDefaultControllerRoute中间
app.MapDefaultControllerRoute();

对 UseAuthentication 的调用是在调用 UseRouting 之后进行的,以便路由信息可用于身份验证决策,但在 UseEndpoints 之前进行,以便用户在访问端点之前进行身份验证。

登录页面

现在我们已经启用了身份验证,我们将需要一个登录页面来验证用户。
首先,创建包含我们验证用户身份所需的信息的登录视图模型。 确保将此文件放入“ViewModels”文件夹中:

using System.ComponentModel.DataAnnotations;namespace AuthorizationServer.ViewModels
{public class LoginViewModel{[Required]public string? Username { get; set; }[Required]public string? Password { get; set; }public string? ReturnUrl { get; set; }}
}

在“Views”文件夹中创建一个名为“Account”的文件夹,并添加登录视图“Login.cshtml”,其中包含登录表单:

@model AuthorizationServer.ViewModels.LoginViewModel<form autocomplete="off" asp-route="Login"><input type="hidden" asp-for="ReturnUrl" /><div class="card"><input type="text" class="form-control form-control-lg" placeholder="Username" asp-for="Username" autofocus><input type="password" class="form-control form-control-lg form-control-last" placeholder="Password" asp-for="Password"></div><p><button type="submit" class="btn btn-dark btn-block mt-3">Login</button></p>
</form>

最后,我们添加AccountController

using AuthorizationServer.ViewModels;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Security.Claims;namespace AuthorizationServer.Controllers
{public class AccountController : Controller{[HttpGet][AllowAnonymous]public IActionResult Login(string returnUrl = null){ViewData["ReturnUrl"] = returnUrl;return View();}[HttpPost][AllowAnonymous][ValidateAntiForgeryToken]public async Task<IActionResult> Login(LoginViewModel model){ViewData["ReturnUrl"] = model.ReturnUrl;if (ModelState.IsValid){var claims = new List<Claim>{new Claim(ClaimTypes.Name, model.Username)};var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);await HttpContext.SignInAsync(new ClaimsPrincipal(claimsIdentity));if (Url.IsLocalUrl(model.ReturnUrl)){return Redirect(model.ReturnUrl);}return RedirectToAction(nameof(HomeController.Index), "Home");}return View(model);}public async Task<IActionResult> Logout(){await HttpContext.SignOutAsync();return RedirectToAction(nameof(HomeController.Index), "Home");}}
}

那么,这里会发生什么?我们在帐户控制器上有两个登录操作(GET 和 POST),都允许匿名请求,否则没有人能够登录。

GET 操作为我们刚刚创建的登录表单提供服务。 我们有一个可选的查询参数 returlUrl ,我们将其存储在 ViewData 中,因此我们可以在成功登录后使用它来重定向用户。

POST 操作更有趣。 首先验证 ModelState。 这意味着需要用户名和密码。 我们在这里不检查凭据,任何组合在此示例中都是有效的。 通常,您可以在此处根据数据库检查凭据。

当 ModelState 有效时,将构建声明身份。 我们添加一项声明,即用户的姓名。 请注意,我们在创建声明身份时指定了 cookie 身份验证方案 (CookieAuthenticationDefaults.AuthenticationScheme)。 这基本上是一个字符串,映射到我们在设置 cookie 身份验证时在 Startup.cs 类中定义的身份验证方案。

SignInAsync方法是一个扩展方法,它调用AuthenticationService,后者调用CookieAuthenticationHandler,因为这是我们在创建声明标识时指定的方案。
登录后我们需要重定向用户。 如果指定了返回 url,我们会在重定向之前检查它是否是本地 url,以防止开放重定向攻击。 否则,用户将被重定向到主页。

最后一个操作Logout调用身份验证服务以注销用户。身份验证服务将调用身份验证中间件,在我们的例子中是cookie身份验证中间件来注销用户。

更新首页

更新主页(Views/Home/Index.cshtml)

@using Microsoft.AspNetCore.Authentication@if (User?.Identity?.IsAuthenticated == true)
{var authenticationResult = await Context.AuthenticateAsync();var issued = authenticationResult?.Properties?.Items[".issued"];var expires = authenticationResult?.Properties?.Items[".expires"];<div><p>You are signed in as</p><h2>@User.Identity.Name</h2><hr /><dl><dt>Issued</dt><dd>@issued</dd><dt>Expires</dt><dd>@expires</dd></dl><hr /><p><a class="btn btn-dark" asp-controller="Account" asp-action="Logout">Sign out</a></p></div>
}@if (User?.Identity?.IsAuthenticated != true)
{<div><p>You are not signed in</p><p><a class="btn btn-sm btn-dark" asp-controller="Account" asp-action="Login">Sign in</a></p></div>
}

如果用户已通过身份验证,我们将显示用户名、当前会话信息和注销按钮。当用户未通过身份验证时,我们会显示一个登录按钮,用于将用户导航到登录表单。
在这里插入图片描述
在这里插入图片描述

账号密码随便输入即可

在这里插入图片描述
退出就会回到登录页面
在这里插入图片描述

目前,我们有一个基本的ASPNET核心项目在运行,并实现了身份验证,到目前为止还没有什么新奇之处。接下来,我们将把OpenIddict添加到项目中,并实现客户端凭据流。

相关文章:

通过OpenIddict设计一个授权服务器02-创建asp.net项目

在这一部分中&#xff0c;我们将创建一个ASPNET核心项目&#xff0c;作为我们授权服务器的最低设置。我们将使用MVC来提供页面&#xff0c;并将身份验证添加到项目中&#xff0c;包括一个基本的登录表单。 创建一个空的asp.net core项目 正如前一篇文章中所说&#xff0c;授权…...

2.6、云负载均衡产品详述

一、定义 弹性负载均衡(Elastic Load Balance&#xff0c;简称ELB)可将来自公网的访问流量分发到后端云主机&#xff0c;可选多种负载均衡策略&#xff0c;并支持自动检测云主机健康状况&#xff0c;消除单点故障&#xff0c;保障应用系统的高可用。 二、产品架构 1&am…...

黑马程序员 Docker笔记

本篇学习笔记文档对应B站视频&#xff1a; 同学们&#xff0c;在前两天我们学习了Linux操作系统的常见命令以及如何在Linux上部署一个单体项目。大家想一想自己最大的感受是什么&#xff1f; 我相信&#xff0c;除了个别天赋异禀的同学以外&#xff0c;大多数同学都会有相同的…...

游戏素材永不缺,免费在线AI工具Scenario功能齐全,简单易用

Scenario是一个在线的AI驱动的工具&#xff0c;主要用于游戏艺术创作。它提供了一套全面的功能&#xff0c;旨在帮助游戏开发者创建与其独特风格和艺术方向相符的独特、高质量的游戏艺术。Scenario的突出特点之一是它的微调能力&#xff0c;允许用户根据独特的风格和艺术方向训…...

ChatGPT和文心一言哪个好用?

#ChatGPT 和文心一言哪个更好用&#xff1f;# 在当今信息爆炸的时代&#xff0c;人们对于文本生成和创作工具的需求越来越高。在这个背景下&#xff0c;ChatGPT和文心一言作为备受瞩目的工具&#xff0c;各自拥有独特的功能和用途。在本文中&#xff0c;我们将深入探讨这两个工…...

纯c++简易的迷宫小游戏

一个用c写的黑框框迷宫 适合新手入门学习 也适合大学生小作业 下面附上代码 总体思路 初始化游戏界面&#xff1a;设置迷宫的大小&#xff08;WIDTH和HEIGH&#xff09;&#xff0c;生成迷宫地图&#xff08;map&#xff09;&#xff0c;包括墙壁、空地、起点和终点。显示…...

基于python舆情分析可视化系统+情感分析+爬虫+机器学习(源码)✅

大数据毕业设计&#xff1a;Python招聘数据采集分析可视化系统✅ 毕业设计&#xff1a;2023-2024年计算机专业毕业设计选题汇总&#xff08;建议收藏&#xff09; 毕业设计&#xff1a;2023-2024年最新最全计算机专业毕设选题推荐汇总 &#x1f345;感兴趣的可以先收藏起来&…...

2024年1月16日Arxiv热门NLP大模型论文:Multi-Candidate Speculative Decoding

大幅提速NLP任务&#xff0c;无需牺牲准确性&#xff01;南京大学提出新算法&#xff0c;大幅提升AI文本生成效率飞跃 引言&#xff1a;探索大型语言模型的高效文本生成 在自然语言处理&#xff08;NLP&#xff09;的领域中&#xff0c;大型语言模型&#xff08;LLMs&#xf…...

AI对决:ChatGPT与文心一言的比较

文章目录 引言ChatGPT与文心一言的比较Chatgpt的看法文心一言的看法Copilot的观点chatgpt4.0的回答 模型的自我评价自我评价 ChatGPT的优势在这里插入图片描述 文心一言的优势AI技术发展趋势总结 引言 在过去的几年里&#xff0c;人工智能&#xff08;AI&#xff09;技术取得了…...

uni-app引用矢量库图标

矢量库引用 导入黑色图标 1.生成连接&#xff0c;下载样式 2.导入项目&#xff08;字体样式&#xff09; 3.引入css样式 4.替换font-face 5.使用图标&#xff08;字体图标&#xff0c;只有黑色&#xff09; 导入彩色图标 1.安装插件 npm install -g iconfont-tools2.…...

Android的setContentView流程

一.Activity里面的mWindow是啥 在ActivityThread的performLaunchActivity方法里面&#xff1a; private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {ActivityInfo aInfo r.activityInfo;if (r.packageInfo null) {r.packageInfo getP…...

【加速排坑】docker设置国内image镜像源

第零步&#xff0c;查看阿里最新的镜像源&#xff1a;https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors 第一步&#xff1a;在/etc/docker/daemon.json中添加镜像源 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-EOF {"registry-m…...

el-table嵌套两层el-dropdown-menu导致样式错乱

问题&#xff1a; 解决方式&#xff1a; <el-table-column label"操作" fixed"right" width"132" align"center"><template slot-scope"scope"><div v-if"scope.row._index ! 合计"><el-d…...

自动化测试:fixture学得好,Pytest测试框架用到老

在pytest中&#xff0c;fixture是一种非常有用的特性&#xff0c;它允许我们在测试函数中注入数据或状态&#xff0c;以便进行测试。而参数化则是fixture的一个特性&#xff0c;它允许我们将不同的数据传递给fixture&#xff0c;从而进行多次测试。 本文将介绍如何在pytest中使…...

Linux上常用网络操作

主机名配置 hostname 查看主机名 hostname xxx 修改主机名 重启后无效 如果想要永久生效&#xff0c;可以修改/etc/sysconfig/network文件 IP地址配置 ifconfig 查看(修改)ip地址(重启后无效) ifconfig eth0 192.168.12.22 修改ip地址 如果想要永久生效,修改 /etc/sysco…...

POI:对Excel的基本读操作 整理2

1 简单读取操作 public class ExcelRead {String PATH "D:\\Idea-projects\\POI\\POI_projects";// 读取的一系列方法// ...... } 因为07版本和03版本操作流程大差不差&#xff0c;所以这边就以03版本为例 Testpublic void testRead03() throws IOException {//获取…...

LeetCode每周五题_2024/01/15~01/19

文章目录 82. 删除排序链表中的重复元素 II题目题解 2744. 最大字符串配对数目题目题解 82. 删除排序链表中的重复元素 II 82. 删除排序链表中的重复元素 II 题目 给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字…...

免费chartGPT网站汇总

https://s.suolj.com - &#xff08;支持文心、科大讯飞、智谱等国内大语言模型&#xff0c;Midjourney绘画、语音对讲、聊天插件&#xff09;国内可以直连&#xff0c;响应速度很快 很稳定 https://seboai.github.io - 国内可以直连&#xff0c;响应速度很快 很稳定 http://gp…...

【分布式微服务专题】SpringSecurity OAuth2快速入门

目录 前言阅读对象阅读导航前置知识笔记正文一、OAuth2 介绍1.1 使用场景*1.2 基本概念&#xff08;角色&#xff09;1.3 优缺点 二、OAuth2的设计思路2.1 客户端授权模式2.1.0 基本参数说明2.1.1 授权码模式2.1.2 简化&#xff08;隐式&#xff09;模式2.1.3 密码模式2.1.4 客…...

Spring Boot实现国际化

src\main\resources\i18n\messages_zh_CN.properties message.hello你好&#xff0c;世界&#xff01; message.welcome欢迎&#xff01; src/main/resources/i18n/messages_en_US.properties message.helloHello World! message.welcomeWelcome! 默认语言 src\main\resources\…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行

项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战&#xff0c;克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...