.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 并查集的相关的操作…...

利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...

vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
全面解析数据库:从基础概念到前沿应用
在数字化时代,数据已成为企业和社会发展的核心资产,而数据库作为存储、管理和处理数据的关键工具,在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理,到社交网络的用户数据存储,再到金融行业的交易记录处理&a…...