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

news/2024/2/29 14:12:53/文章来源:https://blog.csdn.net/qq_36437991/article/details/135604521

在这一部分中,我们将创建一个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添加到项目中,并实现客户端凭据流。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_925594.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PSoc62™开发板之i2c通信

实验目的 使用模拟i2c接口读取温湿度气压模块BME280数据 实验准备 PSoc62™开发板温湿度气压模块BME280公母头杜邦线 板载资源 本次实验是通过模拟i2c时序的方式来进行通信&#xff0c;理论上可以有非常多的方式配置i2c引脚&#xff0c;不像硬件i2c那样芯片出厂引脚已经固…

SpringBoot教程(十二) | SpringBoot集成JPA

SpringBoot教程(十二) | SpringBoot集成JPA 1. JPA简介 概念&#xff1a; JPA顾名思义就是Java Persistence API的意思&#xff0c;是JDK 5.0注解或XML描述对象&#xff0d;关系表的映射关系&#xff0c;并将运行期的实体对象持久化到数据库中。 优势&#xff1a; 标准化 …

信息系统安全——Linux 访问控制机制分析

实验 4 Linux 访问控制机制分析 4.1 实验名称 《Linux 访问控制机制分析》 4.2 实验目的 1 、熟悉 Linux基本访问控制机制使用和原理 2 、熟悉 Linux S 位的作用和使用 3 、熟悉强制访问控制 Selinux 原理及其使用 4.3 实验步骤及内容 1 、Linux 基本访问控制机制 &#xff08…

渗透测试(8)- Kali Linux 系统概述

Kali Linux 是一个基于 Debian 的 Linux 发行版&#xff0c;包括很多安全和取证方面的相关工具。Kali Linux 是一款全功能的安全操作系统&#xff0c;它可以帮助用户完成各种安全任务&#xff0c;包括网络渗透测试、系统攻击、密码破解、恶意软件分析、社会工程学攻击等&#x…

buuctf[极客大挑战 2019]BabySQL--联合注入、双写过滤

目录 1、测试万能密码&#xff1a; 2、判断字段个数 3、尝试联合注入 4、尝试双写过滤 5、继续尝试列数 6、查询数据库和版本信息 7、查询表名 8、没有找到和ctf相关的内容&#xff0c;查找其他的数据库 9、查看ctf数据库中的表 10、查询Flag表中的字段名 11、查询表…

新能源汽车智慧充电桩方案:如何实现充电停车智慧化管理?

一、方案概述 基于新能源汽车充电桩的监管运营等需求&#xff0c;安徽旭帆科技携手合作伙伴触角云共同打造“智能充电设备&#xff0b;云平台&#xff0b;APP小程序”一体化完整的解决方案&#xff0c;为充电桩车位场所提供精细化管理车位的解决办法&#xff0c;解决燃油车恶意…

Python+Django+MySQL的图书馆管理系统【附源码,运行简单】

PythonDjangoMySQL的图书馆管理系统【附源码&#xff0c;运行简单】 总览 1、《图书馆管理系统》1.1 方案设计说明书设计目标需求分析工具列表 2、详细设计2.1 登录2.2 注册2.3 程序主页面2.4 图书新增界面2.5 图书信息修改界面2.6 其他功能贴图 3、下载 总览 自己做的项目&am…

测试覆盖率 之 Cobertura的使用

什么是代码覆盖率&#xff1f; 代码覆盖率是对整个测试过程中被执行的代码的衡量&#xff0c;它能测量源代码中的哪些语句在测试中被执行&#xff0c;哪些语句尚未被执行。 为什么要测量代码覆盖率&#xff1f; 众所周知&#xff0c;测试可以提高软件版本的质量和可预测性。…

【力扣·每日一题】2085.统计出现过一次的公共字符串(模拟 哈希表 优化 C++ Go)

题目链接 题意 给你两个字符串数组 words1 和 words2 &#xff0c;请你返回在两个字符串数组中 都恰好出现一次 的字符串的数目。 输入&#xff1a;words1 [“leetcode”,“is”,“amazing”,“as”,“is”], words2 [“amazing”,“leetcode”,“is”] 输出&#xff1a;2 …

Java爬虫爬取图片壁纸

Java爬虫 以sougou图片为例&#xff1a;https://pic.sogou.com/ JDK17、SpringBoot3.2.X、hutool5.8.24实现Java爬虫&#xff0c;爬取页面图片 项目介绍 开发工具&#xff1a;IDEA2023.2.5 JDK&#xff1a;Java17 SpringBoot&#xff1a;3.2.x 通过 SpringBoot 快速构建开发环境…

Baumer工业相机堡盟工业相机如何使用OpenCV实现相机图像的显示(C#)

Baumer工业相机堡盟工业相机如何使用OpenCV实现相机图像的显示&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机的图像转换为OpenCV的Mat图像的技术背景在NEOAPI SDK里使用OpenCV实现相机图像的显示联合OpenCV实现相机图像的显示测试演示图 工业相机通过使用OpenCV实现…

生产力与生产关系 —— 浅析爱泼斯坦事件 之 弱电控制强电原理

据网络文字与视频资料&#xff0c;爱泼斯坦事件是犹太精英阶层&#xff0c;为了掌控美国国家机器为犹太利益集团服务&#xff0c;而精心设下的一个局。本文先假设这个结论成立&#xff0c;并基于此展开讨论。 我们知道&#xff0c;弱电管理强电是电气工程中的一门专门学问&…

Pandas.DataFrame.groupby() 数据分组(数据透视、分类汇总) 详解 含代码 含测试数据集 随Pandas版本持续更新

关于Pandas版本&#xff1a; 本文基于 pandas2.1.2 编写。 关于本文内容更新&#xff1a; 随着pandas的stable版本更迭&#xff0c;本文持续更新&#xff0c;不断完善补充。 Pandas稳定版更新及变动内容整合专题&#xff1a; Pandas稳定版更新及变动迭持续更新。 Pandas API参…

弟12章 网络编程

文章目录 网络协议概述 p164TCP协议与UDP协议的区别 p165TCP服务器端代码的编写 p166TCP服务器端流程 TCP客户端代码的编写 p167TCP客户端流程主机和客户端的通信流程 tcp多次通信服务器端代码 p168TCP多次通信客户端代码 p169UDP的一次双向通信 p170udp通信模型udp接收方代码u…

生活的再思考,写在开篇

近几年的就业行情很特别&#xff0c;特别是对中年人&#xff0c;早先网络上主流的声音是动不动总包百万&#xff0c;手握几个 Offer &#xff0c;纠结应该去哪里。现在的主流声音变成了&#xff0c;被毕业优化掉后几个月都没找到合适的工作&#xff0c;焦虑迷茫无所适从&#x…

第5章案例课:部署Tomcat及其负载均衡

这个实验需要3台虚拟机 192.168.9.40 9.31 9.32 去FTP 下载软件包 192.168.9.40 和 192.168.9.31 都要这里面的配置[rootnode1 ~]# mount /dev/cdrom /mnt/ //挂载[rootnode1 ~]# rpm -ivh /mnt/Packages/ftp-0.17-67.el7.x86_64.rpm //下载 FTP 软件包[roo…

发送HTTP POST请求并处理响应

发送HTTP POST请求并处理响应是Web开发中的常见任务。在Go语言中&#xff0c;可以使用net/http包来发送HTTP POST请求并处理响应。 以下是一个示例代码&#xff0c;演示了如何发送HTTP POST请求并处理响应&#xff1a; go复制代码 package main import ( "b…

模拟开关灯

1&#xff0e;  实验任务 如图所示&#xff0c;监视开关K1&#xff08;接在P3.0端口上&#xff09;&#xff0c;用发光二极管L1&#xff08;接在单片机P1.0端口上&#xff09;显示开关状态&#xff0c;如果开关合上&#xff0c;L1亮&#xff0c;开关打开&#xff0c;L1熄灭。…

51单片机_电子时钟电子万年历电子闹钟

实物演示效果&#xff1a; https://www.bilibili.com/video/BV1RN4y1Q7dK/?vd_source6ff7cd03af95cd504b60511ef9373a1d 二、液晶对比度的调节 液晶的内容要清晰显示&#xff0c;就要调节电位器来调节液晶的对比度&#xff0c;这个电位器位于液 晶的下面&#xff0c;可以用…

网络服务之DHCP

目录 一、DHCP是什么&#xff1f; 1、DHCP就是动态主机配置协议 2、DHCP的作用&#xff1a; 3、DHCP是应用层协议 二、DHCP的优点 三、DHCP的分配过程 1、自动分配&#xff1a;分配到一个ip地址后永久使用 2、手动配置&#xff1a;由DHCP服务器管理员专门指定ip地址&am…