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

本文涉及的产品
函数计算FC,每月15万CU 3个月
容器镜像服务 ACR,镜像仓库100个 不限时长
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
简介: 本文介绍了如何使用 `.NET CLI` 创建并改造一个 `ASP.NET Core Web API` 项目,以实现基于许可证的授权机制。具体步骤包括创建项目、添加必要的 NuGet 包(如 `Standard.Licensing` 和 `Swashbuckle.AspNetCore`),以及修改 `Program.cs` 文件以集成自定义的许可证验证中间件。项目结构中新增了 `LicenseController` 接口用于处理授权相关操作,并通过测试流程验证了默认天气接口在未授权和授权状态下的响应情况。整个过程确保了应用程序能够在启动时正确验证许可证,保障系统的安全性与可控性。

创建 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 授权模式。

目录
相关文章
|
2月前
|
存储 算法 安全
.NET 平台 SM2 国密算法 License 证书生成深度解析
授权证书文件的后缀通常取决于其编码格式和具体用途。本文档通过一个示例程序展示了如何在 .NET 平台上使用国密 SM2 算法生成和验证许可证(License)文件。该示例不仅详细演示了 SM2 国密算法的实际应用场景,还提供了关于如何高效处理大规模许可证文件生成任务的技术参考。通过对不同并发策略的性能测试,开发者可以更好地理解如何优化许可证生成流程,以满足高并发和大数据量的需求。 希望这段描述更清晰地传达了程序的功能和技术亮点。
172 13
.NET 平台 SM2 国密算法 License 证书生成深度解析
|
1月前
|
机器学习/深度学习 人工智能 搜索推荐
技术革新下的培训新趋势:案例解析
从最初的“试试看”,到如今的“非做不可”,企业培训已经成为央国企和上市公司不可或缺的战略环节。无论是AI与大模型的赋能,DeepSeek,还是具身智能、智算技术和数据科学的实战应用,这些课程都在为企业打开新的可能性。
|
6月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
371 3
|
4月前
|
NoSQL Java Linux
《docker高级篇(大厂进阶):2.DockerFile解析》包括:是什么、DockerFile构建过程解析、DockerFile常用保留字指令、案例、小总结
《docker高级篇(大厂进阶):2.DockerFile解析》包括:是什么、DockerFile构建过程解析、DockerFile常用保留字指令、案例、小总结
347 76
|
4月前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
4月前
|
存储 监控 调度
云服务器成本优化深度解析与实战案例
本文深入探讨了云服务器成本优化的策略与实践,涵盖基本原则、具体策略及案例分析。基本原则包括以实际需求为导向、动态调整资源、成本控制为核心。具体策略涉及选择合适计费模式、优化资源配置、存储与网络配置、实施资源监控与审计、应用性能优化、利用优惠政策及考虑多云策略。文章还通过电商、制造企业和初创团队的实际案例,展示了云服务器成本优化的有效性,最后展望了未来的发展趋势,包括智能化优化、多云管理和绿色节能。
|
5月前
|
存储 人工智能 自然语言处理
高效档案管理案例介绍:文档内容批量结构化解决方案解析
档案文件内容丰富多样,传统人工管理耗时低效。思通数科AI平台通过自动布局分析、段落与标题检测、表格结构识别、嵌套内容还原及元数据生成等功能,实现档案的高精度分块处理和结构化存储,大幅提升管理和检索效率。某历史档案馆通过该平台完成了500万页档案的数字化,信息检索效率提升60%。
|
5月前
|
Prometheus 监控 Cloud Native
实战经验:成功的DevOps实施案例解析
实战经验:成功的DevOps实施案例解析
213 6
|
6月前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
67 1
|
6月前
|
测试技术 API 开发者
精通.NET单元测试:MSTest、xUnit、NUnit全面解析
【10月更文挑战第15天】本文介绍了.NET生态系统中最流行的三种单元测试框架:MSTest、xUnit和NUnit。通过示例代码展示了每种框架的基本用法和特点,帮助开发者根据项目需求和个人偏好选择合适的测试工具。
212 3

推荐镜像

更多