ASP.NET Core 3.0中支持AI的生物识别安全

本文共两个部分,这是第一部分,其中介绍了 ASP.NET Core 3 中旨在将授权逻辑与基本的用户角色相分离的基于策略的授权模型。


此部分提供了此授权进程的基于生物识别信息(如人脸识别或语音识别)的具体示例。


在此示例中,检测到未经授权的入侵时,将限制进入建筑。


Azure 机器学习内置的异常检测服务将评估入侵的严重性。


进入场地


上下文是受高度保护的场地 - 如军区、医院或数据中心。通过一些限制来仅允许已授权的人员进入。下列步骤说明了在各个门口执行的用于进行人员签入的安全流:



  • 要求进入建筑的人员在门口的读卡器上刷其访问通信证。


  • 摄像头检测手势,并捕获此人的面部和肢体;此过程应防止使用诸如打印的照片之类的来欺骗仅具有人脸识别的摄像头。


  • 读卡器和摄像头注册为物联网 (IoT) 设备,并将录制的数据流式传输到 Azure IoT 中心。


  • Microsoft 认知服务将此人与已授权进入建筑的人员数据库进行比较。


  • 授权流将 IoT 设备采集的生物识别信息与访问通信证上的人员身份进行匹配。


  • 调用 Azure 机器学习服务来评估访问申请的风险级别,并评估是否属于未经授权的入侵。


  • ASP.NET Core Web API 核对前面的步骤中定义的配置文件包含的特定策略要求,并授予权限。


若检测到的人员身份与访问通信证不一致,将立即阻止其进入场地。反之,流查看是否存在下面的任何异常,并继续操作:


  • 进入建筑的频率异常。


  • 此人之前是否曾进入此建筑(签出)。


  • 每日允许的访问次数。


  • 此人是否值班。


  • 建筑的关键性(可能无需限制对餐厅的访问,但要对服务器数据中心访问执行严格的策略)。


  • 此人是否带领其他人或携带其他物品同行。


  • 同一个建筑发生过的类似访问异常。


  • 过去评估的风险级别的变化。


  • 过去检测到的入侵次数。


Azure 机器学习运行异常检测服务,此服务返回评分来表示访问偏离标准值的可能性。


使用 0 到 1 之间的数值表示此评分,其中 0 表示“未检测到风险”、一切正常、已受到完全信任;1 表示“红色警报”,要立即阻止进入!对于大于 0 的任意值,由各个建筑的风险级别决定用于允许进入建筑的可接受阈值。


ASP.NET Core 中的授权


ASP.NET Core 提供简单的授权声明性角色和丰富的基于策略的模型。使用要求表示授权,由处理程序针对这些要求评估用户的声明。


为说明如何向要访问场地的用户授权,下文将介绍如何生成自定义策略要求以及其授权处理程序。


有关 ASP.NET Core 中的授权模型的详细信息,请参阅 bit.ly/2UYZaJh 中的文档。


如上所述,自定义的基于策略的授权机制由要求和(通常情况下)授权处理程序组成。授权访问建筑包括调用打开入口门锁的 API。


IoT 设备将生物识别信息流式传输到 Azure IoT 中心,进而通过发送场地 ID(场地的唯一标识符)触发验证工作流。


若验证成功,Web API POST 方法仅返回 HTTP 代码 200 及包含用户名和场地 ID 的 JSON 消息。反之,它引发相应的 HTTP 401“访问未经授权”错误代码。


接下来我们按顺序操作:从 Web API 的 Startup 类开始,ConfigureServices 方法尤为重要,其中包含配置所需服务以运行 ASP.NET Core 应用程序的说明。


在服务对象上调用 AddAuthorization 方法,以添加授权策略。


调用 AddAuthorization 方法以授权其执行时,它接受 API 函数必须拥有的策略集合。在本示例中,仅需要一个策略,我们称其为“AuthorizedUser”。 


但是此策略包含多个要满足的要求,它们反映了要验证的人员的生物特性:面部、肢体和声音。


这三个要求分别由实现 IAuthorizationRequirement 接口的特定类表示,如图 1 所示。列出 AuthorizedUser 策略的要求时,还指定了满足要求所需的可信度。


如前文所述,此值介于 0 和 1 之间,并且表示相应的生物属性识别的准确性。


稍后在探讨使用认知服务进行生物识别时,我们将继续介绍它。


图 1 Web API 中的授权要求的配置


public void ConfigureServices(IServiceCollection services){  var authorizationRequirements = new List<IAuthorizationRequirement>  {    new FaceRecognitionRequirement(confidence: 0.9),    new BodyRecognitionRequirement(confidence: 0.9),    new VoiceRecognitionRequirement(confidence: 0.9)  };  services    .AddAuthorization(options =>    {      options.AddPolicy("AuthorizedUser", policy => policy.Requirements =       authorizationRequirements);    })



AuthorizedUser 授权策略包含多个授权要求,必须满足所有要求才能使策略评估成功。换言之,按照 AND 原则处理添加到单个授权策略的多个授权要求。


在此解决方案中实现的三个策略要求都是实现 IAuthorizationRequirement 接口的类。此接口实际为空;也就是说,它不指示任何方法的实现。


一致通过以下方式实现这三个要求:指定 ConfidenceScore 公共属性来捕获若要视为此要求“成功”识别 API 应达到的预期可信度。


FaceRecognitionRequirement 类如下所示:


public class FaceRecognitionRequirement : IAuthorizationRequirement{  public double ConfidenceScore { get; }  public FaceRecognitionRequirement(double confidence) =>    ConfidenceScore = confidence;}



以同样的方式分别在 BodyRecognitionRequirement 和 VoiceRecognitionRequirement 类中实现针对肢体和语音识别的其他要求。


通过授权属性控制对执行 Web API 操作的授权。简而言之,通过向控制器或操作应用 AuthorizeAttri­bute,来将该控制器或操作的访问权限限制在所有已授权用户范围内。控制场地访问的 Web API 公开单个访问控制器,其中仅包含 Post 操作。


若已满足指定的“AuthorizedUser”策略中的所有要求,将向此操作授权:


[ApiController]public class AccessController : ControllerBase{  [HttpPost]  [Authorize(Policy = "AuthorizedUser")]  public IActionResult Post([FromBody] string siteId)  {    var response = new    {      User = HttpContext.User.Identity.Name,      SiteId = siteId    };    return new JsonResult(response);  }}



由授权处理程序管理各个要求,如图 2 中所示,它负责评估策略要求。可以选择让所有要求共用单个处理程序,也可以选择让各个要求拥有单独的处理程序。


后面的方式更为灵活,因为它允许配置渐变的授权要求,这样就可以轻松地在 Startup 类中配置它们。


面部、肢体和声音要求处理程序扩展 AuthorizationHandler<TRequirement> 抽象类,其中 TRequirement 是要处理的要求。


由于要评估三个要求,因此需要编写自定义处理程序来分别扩展 FaceRecognitionRequirement、BodyRecognitionRequirement 和 VoiceRecognitionRequirement 的 AuthorizationHandler。


具体而言,由 HandleRequirementAsync 方法决定是否满足授权要求。由于此方法为异步方法,因此它不返回实际值,指示任务已完成时除外。


处理授权包括在授权处理程序上下文上调用 Succeed 方法以将要求标记为“成功”。


此过程实际上由“识别器”对象验证,它在内部使用认知服务 API(详见下一部分)。


识别方法执行的识别操作获取所识别人员的姓名,并返回一个值(评分)来可信度,即识别准确度高(值接近 1)或准确度低(值接近 0)。


在 API 设置中指定了预期 API。可以将此值调整为任何适用于解决方案的阈值。


图 2 自定义授权处理程序


public class FaceRequirementHandler :


  AuthorizationHandler<FaceRecognitionRequirement>{  protected override Task HandleRequirementAsync(    AuthorizationHandlerContext context,      FaceRecognitionRequirement requirement)  {    string siteId =      (context.Resource as HttpContext).Request.Query["siteId"];    IRecognition recognizer = new FaceRecognition();    if (recognizer.Recognize(siteId, out string name) >=      requirement.ConfidenceScore)    {      context.User.AddIdentity(new ClaimsIdentity(        new GenericIdentity(name)));      context.Succeed(requirement);    }    return Task.CompletedTask;  }}



除了评估特定要求,授权处理程序还为当前用户添加身份声明。生成身份后,可以为它分配一个或多个由受信任方发布的声明。声明是表示主体身份的姓名-值对。


在此示例中,将为上下文中的用户分配身份声明。


然后在访问控制器的 Post 操作中检索此声明,并将其作为 API 响应的一部分返回。


启用此自定义授权进程的最后一个步骤是注册 Web API 内的处理程序。进行配置时,在服务集合中注册处理程序:


services.AddSingleton<IAuthorizationHandler, FaceRequirementHandler>();services.AddSingleton<IAuthorizationHandler, BodyRequirementHandler>();services.AddSingleton<IAuthorizationHandler, VoiceRequirementHandler>();



此代码使用 ASP.NET Core 的内置依存关系注入 (DI) 框架将各个要求处理程序注册为单一实例。启动应用程序时,将生成此处理程序的实例,依存关系注入将注册的类注入到相关对象。


人脸识别


此解决方案将 Azure 认知服务用于视觉 API,来识别人的面部和肢体。有关认知服务及此 API 的详细信息,请参阅 bit.ly/2sxsqry。


视觉 API 提供人脸属性检测和人脸验证。人脸检测指从图像中检测人脸的功能。


此 API 返回所处理的图像中人脸位置的矩形坐标,还可以提取一系列与人脸相关的属性,如头部姿势、性别、年龄、表情、面部毛发和眼镜。


人脸验证与之相反,它针对人员的预保存人脸验证检测到的人脸。它实际上是在评估两个人脸是否属于同一个人。这是用于此安全项目的特定 API。


请将下面的 NuGet 包添加到 Visual Studio 解决方案,以开始使用:Microsoft.Azure.Cognitive­Services.Vision.Face 2.2.0-preview


.NET 托管的包处于预览状态,因此在浏览 NuGet 时务必选中“包括预发行版”选项,如图 3 所示


640?wx_fmt=png



图 3 人脸 API 的 NuGet 包


.NET 包、人脸检测和人脸识别的用法非常简单。大体而言,人脸识别说明了比较两个不同的人脸以确定它们是否相似或是否属于同一个人的工作过程。识别操作主要使用图 4 列出的数据结构。


图 4 人脸 API 的数据结构


640?wx_fmt=png


验证操作从在图像中检测到的人脸列表(DetectedFace 集合)提取人脸 ID,并将此 ID 与保存的人脸 (PersistedFace) 集合进行比较,来确定这些人脸是否属于同一个人。保存的人脸图像使用唯一的 ID 和名称标识某个人员。


可以选择将一组人员收集到一个 PersonGroup 中,以便改进识别性能。从根本上说,一个人员就是一个基本的身份单位,一个人员对象可以注册一个或多个已知的人脸。


在一个特定的 PersonGroup(人员集合)中定义各个人员,并基于 PersonGroup 完成识别。


安全系统将创建一个或多个 PersonGroup 对象,然后将人员与这些对象关联。


生成组后,必须先定型 PersonGroup 集合,然后才能使用它执行验证。


此外,在添加或删除任何人员或编辑任何人员已注册的人脸后,必须重新定型此集合。由 PersonGroup 定型 API 完成定型。


如果使用的是客户端库,此过程只是对 TrainPersonGroupAsync 方法的调用:


await faceServiceClient.TrainPersonGroupAsync(personGroupId);



定型是异步进程。即使 TrainPersonGroupAsync 方法已返回,此进程可能仍未完成。需要使用 GetPersonGroupTrainingStatusAsync 方法查询定型状态,直至已准备就绪,才可继续执行人脸检测或验证。


执行人脸验证时,人脸 API 计算检测到的人脸与组内所有人脸的相似度,并返回与该测试人脸相似度最高的人员。通过客户端库的 IdentifyAsync 方法完成此过程。需要使用上述步骤检测测试人脸,然后将人脸 ID 作为第二个参数传递到识别 API。


一次可以识别多个人脸 ID,结果将包含所有识别结果。默认情况下,识别仅返回一个与测试人脸匹配度最高的人员。


如有必要,可以指定可选参数 maxNumOfCandidatesReturned,来让识别返回多个候选人。图 5 中的代码演示了识别和验证人脸的过程:


图 5 人脸识别过程


public class FaceRecognition : IRecognition{  public double Recognize(string siteId, out string name)  {    FaceClient faceClient = new FaceClient(      new ApiKeyServiceClientCredentials("<Subscription Key>"))    {      Endpoint = "<API Endpoint>"    };    ReadImageStream(siteId, out Stream imageStream);    // Detect faces in the image    IList<DetectedFace> detectedFaces =   faceClient.Face.DetectWithStreamAsync(imageStream).Result;    // Too many faces detected    if (detectedFaces.Count > 1)    {      name = string.Empty;      return 0;    }    IList<Guid> faceIds = detectedFaces.Select(f => f.FaceId.Value).ToList();    // Identify faces    IList<IdentifyResult> identifiedFaces =      faceClient.Face.IdentifyAsync(faceIds, "<Person Group ID>").Result;    // No faces identified    if (identifiedFaces.Count == 0)    {      name = string.Empty;      return 0;    }    // Get the first candidate (candidates are ranked by confidence)    IdentifyCandidate candidate =      identifiedFaces.Single().Candidates.FirstOrDefault();    // Find the person    Person person =      faceClient.PersonGroupPerson.GetAsync("", candidate.PersonId).Result;    name = person.Name;    return candidate.Confidence;  }



首先需要传递订阅密钥和 API 终结点,来获取人脸 API 的客户端对象。可以从预配人脸 API 服务的 Azure 门户中获取这两个值。然后检测图像中显示的任何人脸,并作为流传递到客户端人脸对象的 DetectWithStreamAsync 方法。


人脸对象实现人脸 API 的检测和验证操作。在检测的人脸中,确保实际只检测一个人脸,并获取其 ID(它是已注册人脸集合中的唯一标识符,该集合中的所有人员已被授权访问该场地)。


然后 IdentifyAsync 方法在 PersonGroup 中识别检测到的人脸,并返回按可信度排序的最佳匹配或候选人列表。通过第一个候选人的人员 ID 检索人员姓名,并且最终会将此姓名返回到访问 Web API。人脸授权要求已满足。


语音识别


Azure 认知服务说话人识别 API 提供说话人验证和说话人识别算法。


声音具有唯一的特性,可以像使用指纹一样将它们用于人员识别。本文中的安全解决方案将语音作为访问控制信号,在此方案中主体通过语音将通行短语输入到已注册为 IoT 设备的麦克风。与人脸识别一样,语音识别也需要预注册已授权的人员。


说话人 API 将已注册人员称为“个人资料”。 注册个人资料时,将录制说话人陈述特定短语时的语音,然后提取一些特性,并识别已选定的短语。提取的特性和已选定的短语共同构成了唯一的语音签名。进行验证时,将输入语音和短语与注册语音签名和短语进行比较,来验证它们是否来自同一个人,以及短语是否正确。


从代码实现可以看出,不同于人员 API,说话人 API 并未从 NuGet 中的托管包受益,因此我们将采用直接使用 HTTP 客户端请求和响应机制调用 REST API 的方法。第一个步骤是使用验证和数据类型的必要参数实例化 HttpClient:


public VoiceRecognition(){  _httpClient = new HttpClient();  _httpClient.BaseAddress = new Uri("<API Endpoint>");  _httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key",    "<Subscription Key>");  _httpClient.DefaultRequestHeaders.Accept.Add(     new MediaTypeWithQualityHeaderValue("application/json"));}



使用下面的几个步骤生成图 6 中的识别方法:从场地中的 IoT 设备获取音频流后,它尝试基于已注册的个人资料集合识别该音频。在 IdentifyAsync 方法中为识别编码。


此异步方法准备包含音频流和识别个人资料 ID 的多部分请求消息,并向特定终结点提交 POST 请求。若 API 的响应为 HTTP 代码 202(已接受),则返回值为在后台运行的操作的 URI。识别方法每 100 毫秒查看一次所标识的 URI 上的该操作是否完成。操作成功后,即获得所识别的人员的个人资料 ID。


借助此 ID,可以继续验证音频流,它将最终确认录制的语音属于所识别的人员。


在 VerifyAsync 方法中实现此操作,此方法的工作原理与 IdentifyAsync 方法类似,但它返回的是包含人员的个人资料及其姓名的 VoiceVerificationResponse 对象。验证响应包含可信度,与人脸 API 一样,同时也会将其返回到访问 Web API。


图 6 语音识别


public double Recognize(string siteId, out string name){  ReadAudioStream(siteId, out Stream audioStream);  Guid[] enrolledProfileIds = GetEnrolledProfilesAsync();  string operationUri =    IdentifyAsync(audioStream, enrolledProfileIds).Result;  IdentificationOperation status = null;  do  {    status = CheckIdentificationStatusAsync(operationUri).Result;    Thread.Sleep(100);  } while (status == null);  Guid profileId = status.ProcessingResult.IdentifiedProfileId;  VoiceVerificationResponse verification =    VerifyAsync(profileId, audioStream).Result;  if (verification == null)  {    name = string.Empty;    return 0;  }  Profile profile = GetProfileAsync(profileId).Result;  name = profile.Name;  return ToConfidenceScore(verification.Confidence);}



我要为此 API 添加一些额外说明,以表明它与人脸 API 的区别。语音验证 API 返回 JSON 对象,其中包含验证操作(接受或拒绝)、可信度(低、中、高)和识别的短语的整体结果:


{  "result" : "Accept", // [Accept | Reject]  "confidence" : "Normal", // [Low | Normal | High]  "phrase": "recognized phrase"}



此对象映射到 VoiceVerificationResponse C# 类,以便于在 VerifyAsync 方法中运行它,但它的可信度使用文本表示:


public class VoiceVerificationResponse{  [JsonConverter(typeof(StringEnumConverter))]  public Result Result { get; set; }  [JsonConverter(typeof(StringEnumConverter))]  public Confidence Confidence { get; set; }  public string Phrase { get; set; }}



而访问 Web API 需要介于 0 到 1 之间的小数值(双精度数据类型),因此为可信度枚举指定了一些数字值:


public enum Confidence{  Low = 1,  Normal = 50,  High = 99}



然后在将这些值返回到访问 Web API 之前,将它们转换为双精度值:


private double ToConfidenceScore(Confidence confidence){  return (double)confidence / 100.0d;}



总结


这是第一部分的全部内容,此部分说明了整个场地访问安全流,并介绍了如何使用自定义策略和要求实现 ASP.NET Core Web API 中的授权机制。


之后说明了如何使用相关的认知服务 API 完成人脸和语音识别,来作为基于已预授权或已注册人员个人资料的生物识别信息限制访问的机制。


本文的第二个部分将详细介绍作为请求访问触发点的 IoT 设备数据流,以及访问 API 最终确认打开(或锁定)入口的过程。


此外,还将说明每当尝试访问时都会运行以识别其风险的基于机器学习的异常检测服务。


从 GitHub 获取此解决方案的第一部分的源代码:bit.ly/2IXPZCo。



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

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

相关文章

架构杂谈《五》

保证最终一致性的模式在大规模、高并发服务化系统中&#xff0c;一个功能被拆分成多个具有功能单一的子功能&#xff0c;一个流程会有多个系统的多个单一功能的服务组合实现&#xff0c;如果使用两阶段提交协议和三阶段提交协议&#xff0c;确实能解决系统间的一致性问题。其实…

在Linux的Windows子系统上(WSL)使用Docker(Ubuntu)

背景平时开发大部人都是在提供了高效GUI的window下工作&#xff0c;但是真正部署环境普遍都是在Linux中&#xff0c;所以为了让开发环境和部署环境统一&#xff0c;我们需要在windows模拟LInux环境&#xff0c;以前我们可能通过虚拟机的方式实现&#xff0c;不过自从微软拥抱开…

.net持续集成cake篇之cake介绍及简单示例

cake介绍Cake 是.net平台下的一款自动化构建工具,可以完成对.net项目的编译,打包,运行单元测试,集成测试甚至发布项目等等.如果有些特征Cake没有实现,我们还可以很容易地通过扩展Cake来实现我们想要的功能.Cake有以下特点1) 使用c#语言编写,可以在Cake脚本里使用C#语言来实现我…

Educational Codeforces Round 73 (Rated for Div. 2) Make The Fence Great Again dp + 结论

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 首先证明一个结论&#xff1a;一个数最多被加两次。 首先假设a[i]a[i−1]a[i]a[i-1]a[i]a[i−1]或a[i]a[i1]a[i]a[i1]a[i]a[i1]&#xff0c;那么此时可以将a[i]a[i]1a[i]a[i]1a[i]a[i]1&am…

.NET Core 3.0 发布小尺寸 self-contained 单体可执行程序

.NET Core 提供的发布应用程序选项 self-contained 是共享应用程序的好方法&#xff0c;因为应用程序的发布目录包含所有组件、运行时和框架。您只需要告诉使用者应用程序的入口 exe 文件&#xff0c;就可以使程序运行起来&#xff0c;而不必担心目标计算机上是否存在.NET Core…

Educational Codeforces Round 73 (Rated for Div. 2) E. Game With String 思维博弈 好题(2500)

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 我们将每一段...拿出来看成若干段&#xff0c;将其分成以下四种情况&#xff1a; (1)len<b(1)len<b(1)len<b (2)b≤len<a(2)b\le len<a(2)b≤len<a (3)a≤len<2∗b(3…

「Sqlserver」数据分析师有理由爱Sqlserver之三-最值得使有低投入高产出的Sqlserver功能...

数据分析师群体&#xff0c;有别于一般的传统开发群体和数据库运维群体&#xff0c;对Sqlserver的功能需求上也各不相同&#xff0c;本篇以笔者的亲身经历&#xff0c;用一种有别于一般性教程的角度来讲解Sqlserver值得我们学习&#xff0c;投入产出比高的一些功能模块。当然&a…

.NET开发框架(八)-服务器集群之网络负载平衡(视频)

【视频教程在文章底部】&#xff0c;本文讲解Windows服务器集群的网络负载平衡NLB的作用&#xff0c;以及在.NET开发框架的架构设计中&#xff0c;如何应用NLB与ARR&#xff0c;使用它们各有什么优点。视频教程目录&#xff1a;1、讲解NLB概念与演示其作用 2、安装配置负载均衡…

人生如戏,别太入戏

这里是Z哥的个人公众号每周五早8点 按时送达当然了&#xff0c;也会时不时加个餐&#xff5e;我的第「81」篇原创敬上大家好&#xff0c;我是Z哥。对&#xff0c;就是脑袋很大的那个。大到什么程度呢&#xff1f;我给新来的小伙伴们说说。我昨天还打算配副新眼镜来着&#xff0…

C#只用属性来解决兔子,不用方法和循环

属性在调用者看来就像一个普通的变量&#xff0c;但作为类的设计者&#xff0c;你可以利用属性来隐藏你类中的一些字段&#xff0c;使外界只能通过属性来访问你的字段&#xff0c;你可以通过属性来限制外界对你的字段的存取&#xff0c;就利用get、set。如果想让用户随意存取你…

.netcore项目docker化,以及docker之间通信

简言&#xff1a;最近刚完成公司的新系统&#xff0c;系统使用的是微服务架构&#xff0c;由于领导说要将服务docker化。下面将我的研究结果分享出来&#xff0c;如若有错误的地方&#xff0c;还请各位大佬多多指点。目录&#xff1a;  什么是docker&#xff1f;使用docker有…

Codeforces Round #592 (Div. 2) F. Chips 构造 + 细节

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 恶心的构造题&#xff0c;思路很简单但是代码细节很多&#xff0c;搞了半天。 根据题目的性质不难发现&#xff0c;如果有两个相同颜色的球相邻&#xff0c;那么他们的颜色永远不会改变。 …

.NET CORE 多语言实现方案

根据市场需求&#xff0c;基于.NET CORE平台开发的RoadFlow工作流平台需要实现多语言版本。经过方案讨论和比对&#xff0c;决定采用.NET自带的本地化功能来实现多语言。话不多说&#xff0c;直接上实现方式。首先修改Startup.cs在public void ConfigureServices(IServiceColle…

中国程序员,请挺起你的腰杆!

这两天发生一个事&#xff0c;登月50周年之际&#xff0c;阿波罗11号制导计算机&#xff08;AGC&#xff09;指令和登月模块的源代码在Github上发布公开了&#xff0c;大量中国人前往围观&#xff0c;把issues区当成了论坛版块灌水留言。猎奇起哄本为消遣作乐&#xff0c;有不妥…

Codeforces Round #592 (Div. 2) G. Running in Pairs 构造(水)

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 史上最水GGG题&#xff0c;没有之一。 考虑最小的情况如何构造&#xff0c;显然就是让a,ba,ba,b都1−n1-n1−n依次排列即可&#xff0c;这样的最小值为n∗(n1)2\frac{n*(n1)}{2}2n∗(n1)​…

Async,Await和ConfigureAwait的关系

在.NET Framework 4.5中&#xff0c;async / await关键字已添加到该版本中&#xff0c;简化多线程操作&#xff0c;以使异步编程更易于使用。为了最大化利用资源而不挂起UI&#xff0c;你应该尽可能地尝试使用异步编程。虽然async / await让异步编程更简单&#xff0c;但是有一…

Educational Codeforces Round 75 (Rated for Div. 2) E2. Voting (Hard Version) 贪心

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; n≤2e5,m≤n,p≤1e9n\le2e5,m\le n,p\le 1e9n≤2e5,m≤n,p≤1e9 思路&#xff1a; 首先需要发现一些性质&#xff0c;假设preipre_iprei​代表所有mj<im_j< imj​<i的pjp_jpj​和。可以发现&#…

DevOps案例研究:知人善任——Google敏捷核心文化

内容来源&#xff1a;DevOps案例深度研究-Google敏捷实践战队&#xff0c;本文只展示部分PPT及研究成果&#xff0c;更多细节请关注案例分享会。本文内容贡献者&#xff1a;陈霁、刘翀、谈佳婧、张霖。阅读干货前先感受一下热烈的氛围~一、Google如何快速交付原型1.1 Savioke公…

在 VS Code 中轻松 review GitHub Pull Requests

相信大家在平时工作或者自己的项目中&#xff0c;一定都有在 GitHub 上进行 Code Review 的经历。对于韩老师来说&#xff0c;不论是平时工作的项目&#xff0c;还是自己的业余项目&#xff0c;代码基本都是在 GitHub 上。所以&#xff0c;在 GitHub 上进行 Pull Requests 的 C…

火热的云原生到底是什么?一文了解云原生四要素!

所谓云原生&#xff0c;它不是一个产品&#xff0c;而是一套技术体系和一套方法论&#xff0c;而数字化转型是思想先行&#xff0c;从内到外的整体变革。更确切地说&#xff0c;它是一种文化&#xff0c;更是一种潮流&#xff0c;是云计算的一个必然导向。随着虚拟化技术的成熟…