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

.net8 使用 license 证书授权案例解析

创建 webapi 项目

使用 .NET CLI 创建一个 ASP.NET Core Web API 应用,并添加指定的 NuGet 包,可以按照以下步骤操作:

  • 创建 ASP.NET Core Web API 项目:
dotnet new webapi -n WebAppLicense
cd WebAppLicense
  • 添加 Standard.Licensing 包:
dotnet add package Standard.Licensing --version 1.2.1
  • 添加 Swashbuckle.AspNetCore 包:
dotnet add package Swashbuckle.AspNetCore --version 7.3.1
  • 验证 csproj 文件: 打开 WebAppLicense.csproj 文件,确保以下内容已添加:
<Project Sdk="Microsoft.NET.Sdk.Web"><PropertyGroup><TargetFramework>net8.0</TargetFramework><Nullable>enable</Nullable><ImplicitUsings>enable</ImplicitUsings></PropertyGroup><ItemGroup><PackageReference Include="Standard.Licensing" Version="1.2.1" /><PackageReference Include="Swashbuckle.AspNetCore" Version="7.3.1" /></ItemGroup></Project>

到此处可以启动运行项目,目的是验证默认环境是否正确,确保进入下一环节的正常运行。

改造项目使用 license 授权

项目结构

依照如下项目结构改造,信息如下:

请添加图片描述

修改 Program.cs 文件

修改 Program.cs 文件,代码如下:

using System.Net.Mime;
using WebAppLicense.Services;
using WebAppLicense.Environments;
using WebAppLicense.Middlewares;var builder = WebApplication.CreateBuilder(args);// Add services to the container.builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();// 添加服务到容器
builder.Services.AddSingleton<ILicenseService, LicenseService>();var app = builder.Build();// 使用自定义许可证验证中间件
// app.UseLicenseValidation();// 在应用启动时验证许可证(此处可封装扩展中间件UseLicenseValidation)
#region 在应用启动时验证许可证
// 定义响应报文类型
string contentType = $"{MediaTypeNames.Text.Plain};charset=utf-8";
// 定义要跳过的路由路径
List<string> skipPaths = ["/api/License/activate", "/api/License/types"];app.Use(async (context, next) =>
{HttpContext httpContext = context;var pathString = httpContext.Request.Path;// 检查当前请求路径是否与 Swagger 相关if (pathString.StartsWithSegments("/swagger")|| pathString.StartsWithSegments("/scalar")|| pathString.StartsWithSegments("/favicon.ico")){await next(httpContext);return;}// 检查当前请求路径是否在跳过列表中if (skipPaths.Contains(pathString)){await next(httpContext);return;}// 假设许可证内容存储在环境变量中var licenseContentBase64 = Environment.GetEnvironmentVariable(LicenseEnv.LICENSE_CONTENT_SECRET);if (string.IsNullOrEmpty(licenseContentBase64)){httpContext.Response.StatusCode = StatusCodes.Status403Forbidden;httpContext.Response.ContentType = contentType;await httpContext.Response.WriteAsync("许可证未提供。");return;}var licenseService = httpContext.RequestServices.GetRequiredService<ILicenseService>();var (isValid, msg) = licenseService.ValidateLicense(licenseContentBase64);if (!isValid){httpContext.Response.StatusCode = StatusCodes.Status403Forbidden;httpContext.Response.ContentType = contentType;await httpContext.Response.WriteAsync($"许可证无效。{msg}");return;}// 如果许可证有效,继续处理请求await next(httpContext);
});
#endregion// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{app.UseSwagger();app.UseSwaggerUI();
}app.UseAuthorization();
app.MapControllers();
await app.RunAsync();
项目相关接口
  • 默认天气接口,WeatherForecastController
using Microsoft.AspNetCore.Mvc;
using WebAppLicense.Model.ViewModel;namespace WebAppLicense.Controllers;[ApiController]
[Route("[controller]")]
public class WeatherForecastController(ILogger<WeatherForecastController> logger) : ControllerBase
{private static readonly string[] Summaries =["Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"];[HttpGet(Name = "GetWeatherForecast")]public IEnumerable<WeatherForecast> Get(){return Enumerable.Range(1, 3).Select(index => new WeatherForecast{Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),TemperatureC = Random.Shared.Next(-20, 55),Summary = Summaries[Random.Shared.Next(Summaries.Length)]}).ToArray();}
}
  • 新增 license 接口,LicenseController
using Microsoft.AspNetCore.Mvc;
using WebAppLicense.Model.ViewModel;
using WebAppLicense.Services;namespace WebAppLicense.Controllers;[Route("api/[controller]")]
[ApiController]
public class LicenseController(ILicenseService licenseService) : ControllerBase
{// 提供的 license 授权类型[HttpGet("types")]public Dictionary<string, int> GetLicenseTypes(){var licenseTypes = licenseService.GetLicenseTypes();return licenseTypes;}// 激活 license 授权[HttpPost("activate")]public async Task<IActionResult> ActivateLicense([FromBody] LicenseActivationRequest request){var licenseContent = await licenseService.GenerateLicenseAsync(request);return Ok(new {request.LicenseType,License = licenseContent,});}
}
  • ILicenseService 服务
using WebAppLicense.Model.ViewModel;namespace WebAppLicense.Services;public interface ILicenseService
{Dictionary<string, int> GetLicenseTypes();ValueTask<string> GenerateLicenseAsync(LicenseActivationRequest request, bool isSaveLicenseFile = false);(bool state, string msg) ValidateLicense(string licenseContentBase64);
}

项目基本信息解释到此,其他详细信息,请查看 WebAppLicense 项目。

授权测试

启动项目,显示页面信息如下:

项目信息

项目相关接口信息说明:

  • WeatherForecast

默认的天气接口,用于测试项目是否使用授权模式,如果为授权则提示相应的信息。

  • License

新增的接口,分别用于提供授权类型和授权激活(通过密钥方式),因此这两个接口被设置为 白名单

测试流程如下:

首先访问接口 /WeatherForecast,执行如下命令,

curl -X 'GET' \'http://localhost:5089/WeatherForecast' \-H 'accept: text/plain'

输出信息:

接口输出信息

从接口返回信息,可以看出该接口在未获得授权 license 的时候被请求。

此时我们使用授权激活接口,通过密钥方式激活授权 license,然后再次访问接口 /WeatherForecast,查看接口响应信息,验证接口是否已经授权。

  • api/License/types

访问接口,执行如下命令:

curl -X 'GET' \'http://localhost:5089/api/License/types' \-H 'accept: text/plain'

接口输出信息:

License/types响应信息

  • api/License/activate

访问接口,执行如下命令:

curl -X 'POST' \'http://localhost:5089/api/License/activate' \-H 'accept: */*' \-H 'Content-Type: application/json' \-d '{"licenseType": "trial","utilization": 5,"passPhrase": "123456","expirationDate": "2025-03-03T13:30:02.644Z","userName": "jeff","email": "jeff@qq.com","productFeatures": {"additionalProp1": "yes","additionalProp2": "no","additionalProp3": "yes"}
}'

接口输出信息:

License/activate响应信息

可以看出,上面两个白名单 中的接口均可访问,接下来我们再次访问默认的天气接口 /WeatherForecast,验证是否被授权激活。

  • WeatherForecast

再次执行同样的命令:

curl -X 'GET' \'http://localhost:5089/WeatherForecast' \-H 'accept: text/plain'

输出信息:

WeatherForecast接口授权响应

通过我们上面两次的接口测试验证,默认天气接口已经正常响应数据,说明该应用程序已经使用了 License 授权模式。

相关文章:

.net8 使用 license 证书授权案例解析

创建 webapi 项目 使用 .NET CLI 创建一个 ASP.NET Core Web API 应用&#xff0c;并添加指定的 NuGet 包&#xff0c;可以按照以下步骤操作&#xff1a; 创建 ASP.NET Core Web API 项目&#xff1a; dotnet new webapi -n WebAppLicense cd WebAppLicense添加 Standard.Li…...

golang的io

https://www.bilibili.com/video/BV1gx4y1r7xb 1. 原生io包 io包是Go语言标准库中底层的I/O接口层&#xff0c;定义了通用的读写规则和错误处理逻辑。每次读写都是直接调用底层系统 I/O&#xff0c;每次读取1字节&#xff0c;系统调用次数多。适用于小数据量、实时性要求高。i…...

全向广播扬声器在油气田中的关键应用 全方位守护安全

油气田作为高风险作业场所&#xff0c;安全生产始终是重中之重。在紧急情况下&#xff0c;如何快速、有效地传达信息&#xff0c;确保人员安全撤离&#xff0c;是油气田安全管理的关键环节。全向广播扬声器凭借其全方位覆盖、高音质输出和强大的环境适应性&#xff0c;成为油气…...

76.读取计时器运行时间 C#例子 WPF例子

TimerManager&#xff1a;一个增强的定时器类&#xff0c;带时间管理功能 在使用定时器时&#xff0c;我们常常需要知道定时器的运行状态&#xff0c;比如它已经运行了多久&#xff0c;或者还剩下多少时间。然而&#xff0c;.NET 的 System.Timers.Timer 类本身并没有直接提供…...

嵌入式开发:傅里叶变换(5):基于STM32,实现CMSIS中的DSP库

目录 步骤 1&#xff1a;准备工作 步骤 2&#xff1a;创建 Keil 项目&#xff0c;并配置工程 步骤 3&#xff1a;在MDK工程上添加 CMSIS-DSP 库 步骤 5&#xff1a;编写代码 步骤 6&#xff1a;配置时钟和优化 步骤 7&#xff1a;调试与验证 步骤 8&#xff1a;优化和调…...

探秘基带算法:从原理到5G时代的通信变革【六】CRC 校验

文章目录 2.5 CRC 校验2.5.1 前言2.5.2 CRC算法简介2.5.3 CRC计算的详细过程2.5.4 CRC校验的两种方法详解**分离比较法****整体运算法****不同位出错与余数的关系****总结** 2.5.5 CRC计算的C实现及工具介绍**C实现CRC计算****CRC计算工具推荐** **2.5.6 总结&#xff1a;CRC校…...

MySQL——DQL、多表设计

目录 一、DQL 1.基本查询 2.条件查询 3.分组查询 4.排序查询 5.分页查询 二、多表设计 1.一对多 2.一对一 3.多对多 一、DQL 1.基本查询 注意&#xff1a; *号代表查询所有字段&#xff0c;在实际开发中尽量少用&#xff08;不直观、影响效率&#xff09; 2.条件查询…...

XML 编辑器:全面指南与最佳实践

XML 编辑器:全面指南与最佳实践 引言 XML(可扩展标记语言)编辑器是处理XML文件的关键工具,对于开发人员、系统管理员以及任何需要处理XML数据的人来说至关重要。本文将全面介绍XML编辑器的概念、功能、选择标准以及最佳实践,旨在帮助读者了解如何选择和使用合适的XML编辑…...

【USRP】NVIDIA Sionna:用于 6G 物理层研究的开源库

目录 Sionna&#xff1a;用于 6G 物理层研究的开源库主要特点实现6G研究的民主化支持 5G、6G 等模块化、可扩展、可伸缩快速启动您的研究 好处原生人工智能支持综合研究平台开放生态系统 安装笔记使用 pip 安装基于Docker的安装从源代码安装“你好世界&#xff01;”探索锡奥纳…...

DeepSeek开源周Day6:DeepSeek V3、R1 推理系统深度解析,技术突破与行业启示

DeepSeek 在开源周第六天再次发文&#xff0c;中文原文、官方号在知乎 DeepSeek - 知乎DeepSeek-V3 / R1 推理系统概览 - 知乎deepseek-ai/open-infra-index: Production-tested AI infrastructure tools for efficient AGI development and community-driven innovation 引言 …...

intra-mart实现logicDesigner与forma联动

一、前言 有一个需求&#xff0c;想实现从页面上传一个excel文件&#xff0c;点击提交&#xff0c;就转发给forma模块&#xff0c;然后用户在forma模块里&#xff0c;确认下自动填写的信息是否正确&#xff0c;正确的话就点击保存&#xff0c;存入数据库&#xff1b;不正确的话…...

《大语言模型的原理发展与应用》:此文为AI自动生成

《大语言模型的原理发展与应用》&#xff1a;此文为AI自动生成 一、引言&#xff1a;大语言模型&#xff0c;AI 时代的 “新引擎” 在当今数字化浪潮中&#xff0c;大语言模型宛如一颗璀璨的明星&#xff0c;照亮了人工智能发展的道路&#xff0c;成为推动各领域变革的核心驱…...

生态安全相关

概念&#xff1a;生态安全指一个国家具有支撑国家生存发展的较为完整、不受威胁的生态系统&#xff0c;以及应对内外重大生态问题的能力。 &#xff08;1&#xff09;国外生态安全的研究进展 国际上对生态安全的研究是从“环境”与“安全”之间的关系展开的。开始的阶段&#x…...

DeepSeek-R1国产化系统gpu驱动+cuda+ollama+webui可视化离线私有化部署

1.概述 网上大部分教程都是在线部署&#xff0c;完全离线私有化部署的文章不多&#xff0c;本文介绍从GPU驱动、cuda、ollama、deepseek模型和open webui等完全离线安装几个方面&#xff0c;让小白0基础也可以私有化部署大模型deepseek-R1。 我使用的设备是银河麒麟V10操作系统…...

数据集/API 笔记:新加坡风速 API

data.gov.sg 数据范围&#xff1a;2016年12月 - 2025年3月 API 查询方式 curl --request GET \--url https://api-open.data.gov.sg/v2/real-time/api/wind-speedcurl --request GET \--url "https://api-open.data.gov.sg/v2/real-time/api/wind-speed?date2024-07-16…...

transformer架构解析{掩码,(自)注意力机制,多头(自)注意力机制}(含代码)-3

目录 前言 掩码张量 什么是掩码张量 掩码张量的作用 生成掩码张量实现 注意力机制 学习目标 注意力计算规则 注意力和自注意力 注意力机制 注意力机制计算规则的代码实现 多头注意力机制 学习目标 什么是多头注意力机制 多头注意力计算机制的作用 多头注意力机…...

【C++】switch 语句编译报错:error: jump to case label

/home/share/mcrockit_3588/prj_linux/../source/rkvpss.cpp: In member function ‘virtual u32 CRkVpss::Control(u32, void*, u32)’: /home/share/mcrockit_3588/prj_linux/../source/rkvpss.cpp:242:8: error: jump to case label242 | case emRkComCmd_DBG_SaveInput:|…...

linux中使用firewall命令操作端口

一、开放端口 1. 开放一个端口 sudo firewall-cmd --zonepublic --add-port8443/tcp --permanent sudo firewall-cmd --reload 2. 开放一组连续端口 sudo firewall-cmd --zonepublic --add-port100-500/tcp --permanent sudo firewall-cmd --reload 3. 一次开放多个不连续…...

C++第六节:stack和queue

本节目标&#xff1a; stack的介绍与使用queue的介绍与使用priority_queue的介绍与使用容器适配器模拟实现与结语 1 stack&#xff08;堆&#xff09;的介绍 stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;只能从容器的一端进行元素的插…...

算法 并查集

目录 前言 一 并查集的思路 二 并查集的代码分析 三 实操我们的代码 四 并查集的代码优化 总结 前言 并查集主要是用来求解集合问题的&#xff0c;用来查找集合还有就是合并集合&#xff0c;可以把这个运用到最小生成树里面 一 并查集的思路 1 并查集的相关的操作…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...