.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'
接口输出信息:

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"}
}'
接口输出信息:

可以看出,上面两个白名单 中的接口均可访问,接下来我们再次访问默认的天气接口 /WeatherForecast,验证是否被授权激活。
WeatherForecast
再次执行同样的命令:
curl -X 'GET' \'http://localhost:5089/WeatherForecast' \-H 'accept: text/plain'
输出信息:

通过我们上面两次的接口测试验证,默认天气接口已经正常响应数据,说明该应用程序已经使用了 License 授权模式。
相关文章:
.net8 使用 license 证书授权案例解析
创建 webapi 项目 使用 .NET CLI 创建一个 ASP.NET Core Web API 应用,并添加指定的 NuGet 包,可以按照以下步骤操作: 创建 ASP.NET Core Web API 项目: dotnet new webapi -n WebAppLicense cd WebAppLicense添加 Standard.Li…...
golang的io
https://www.bilibili.com/video/BV1gx4y1r7xb 1. 原生io包 io包是Go语言标准库中底层的I/O接口层,定义了通用的读写规则和错误处理逻辑。每次读写都是直接调用底层系统 I/O,每次读取1字节,系统调用次数多。适用于小数据量、实时性要求高。i…...
全向广播扬声器在油气田中的关键应用 全方位守护安全
油气田作为高风险作业场所,安全生产始终是重中之重。在紧急情况下,如何快速、有效地传达信息,确保人员安全撤离,是油气田安全管理的关键环节。全向广播扬声器凭借其全方位覆盖、高音质输出和强大的环境适应性,成为油气…...
76.读取计时器运行时间 C#例子 WPF例子
TimerManager:一个增强的定时器类,带时间管理功能 在使用定时器时,我们常常需要知道定时器的运行状态,比如它已经运行了多久,或者还剩下多少时间。然而,.NET 的 System.Timers.Timer 类本身并没有直接提供…...
嵌入式开发:傅里叶变换(5):基于STM32,实现CMSIS中的DSP库
目录 步骤 1:准备工作 步骤 2:创建 Keil 项目,并配置工程 步骤 3:在MDK工程上添加 CMSIS-DSP 库 步骤 5:编写代码 步骤 6:配置时钟和优化 步骤 7:调试与验证 步骤 8:优化和调…...
探秘基带算法:从原理到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 总结:CRC校…...
MySQL——DQL、多表设计
目录 一、DQL 1.基本查询 2.条件查询 3.分组查询 4.排序查询 5.分页查询 二、多表设计 1.一对多 2.一对一 3.多对多 一、DQL 1.基本查询 注意: *号代表查询所有字段,在实际开发中尽量少用(不直观、影响效率) 2.条件查询…...
XML 编辑器:全面指南与最佳实践
XML 编辑器:全面指南与最佳实践 引言 XML(可扩展标记语言)编辑器是处理XML文件的关键工具,对于开发人员、系统管理员以及任何需要处理XML数据的人来说至关重要。本文将全面介绍XML编辑器的概念、功能、选择标准以及最佳实践,旨在帮助读者了解如何选择和使用合适的XML编辑…...
【USRP】NVIDIA Sionna:用于 6G 物理层研究的开源库
目录 Sionna:用于 6G 物理层研究的开源库主要特点实现6G研究的民主化支持 5G、6G 等模块化、可扩展、可伸缩快速启动您的研究 好处原生人工智能支持综合研究平台开放生态系统 安装笔记使用 pip 安装基于Docker的安装从源代码安装“你好世界!”探索锡奥纳…...
DeepSeek开源周Day6:DeepSeek V3、R1 推理系统深度解析,技术突破与行业启示
DeepSeek 在开源周第六天再次发文,中文原文、官方号在知乎 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联动
一、前言 有一个需求,想实现从页面上传一个excel文件,点击提交,就转发给forma模块,然后用户在forma模块里,确认下自动填写的信息是否正确,正确的话就点击保存,存入数据库;不正确的话…...
《大语言模型的原理发展与应用》:此文为AI自动生成
《大语言模型的原理发展与应用》:此文为AI自动生成 一、引言:大语言模型,AI 时代的 “新引擎” 在当今数字化浪潮中,大语言模型宛如一颗璀璨的明星,照亮了人工智能发展的道路,成为推动各领域变革的核心驱…...
生态安全相关
概念:生态安全指一个国家具有支撑国家生存发展的较为完整、不受威胁的生态系统,以及应对内外重大生态问题的能力。 (1)国外生态安全的研究进展 国际上对生态安全的研究是从“环境”与“安全”之间的关系展开的。开始的阶段&#x…...
DeepSeek-R1国产化系统gpu驱动+cuda+ollama+webui可视化离线私有化部署
1.概述 网上大部分教程都是在线部署,完全离线私有化部署的文章不多,本文介绍从GPU驱动、cuda、ollama、deepseek模型和open webui等完全离线安装几个方面,让小白0基础也可以私有化部署大模型deepseek-R1。 我使用的设备是银河麒麟V10操作系统…...
数据集/API 笔记:新加坡风速 API
data.gov.sg 数据范围: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
本节目标: stack的介绍与使用queue的介绍与使用priority_queue的介绍与使用容器适配器模拟实现与结语 1 stack(堆)的介绍 stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,只能从容器的一端进行元素的插…...
算法 并查集
目录 前言 一 并查集的思路 二 并查集的代码分析 三 实操我们的代码 四 并查集的代码优化 总结 前言 并查集主要是用来求解集合问题的,用来查找集合还有就是合并集合,可以把这个运用到最小生成树里面 一 并查集的思路 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】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
站群服务器的应用场景都有哪些?
站群服务器主要是为了多个网站的托管和管理所设计的,可以通过集中管理和高效资源的分配,来支持多个独立的网站同时运行,让每一个网站都可以分配到独立的IP地址,避免出现IP关联的风险,用户还可以通过控制面板进行管理功…...
