RT.MesWeb.Authentication 1.2.0

dotnet add package RT.MesWeb.Authentication --version 1.2.0
                    
NuGet\Install-Package RT.MesWeb.Authentication -Version 1.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="RT.MesWeb.Authentication" Version="1.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RT.MesWeb.Authentication" Version="1.2.0" />
                    
Directory.Packages.props
<PackageReference Include="RT.MesWeb.Authentication" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add RT.MesWeb.Authentication --version 1.2.0
                    
#r "nuget: RT.MesWeb.Authentication, 1.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package RT.MesWeb.Authentication@1.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=RT.MesWeb.Authentication&version=1.2.0
                    
Install as a Cake Addin
#tool nuget:?package=RT.MesWeb.Authentication&version=1.2.0
                    
Install as a Cake Tool

Authentication 使用说明

安装

dotnet add package RT.MesWeb.Authentication

目标框架:net8.0 / net10.0

快速开始

  1. 引用模块:启动模块标注 [DependsOn(typeof(AuthenticationApiModule))]。
  2. 配置 appsettings.json:至少填 Authentication:AuthEntities:ConnectionString(唯一必填项)。
  3. 注册服务(构建前):调用 services.RegisterModules(configuration)——AuthenticationApiModule 会自动完成 IHttpContextAccessor、JwtOptions/AuthenticationOptions、AuthEntities DbContext、JWT Bearer 认证及各服务的注册;多语言仍需在主工程单独注册。
  4. 启动授权服务:MesLicenseChecker.Current.Start(...)。
  5. 可选:注册 ILoginProvider 扩展登录程序。

完整代码片段见下文「使用说明」。

配置要求

  • 需要在 appsettings.json 中添加以下配置:
  • 必填:仅 Authentication:AuthEntities:ConnectionString 一项(无默认值)。其余配置均有默认值,可按需覆盖。
  • 安全提示:SystemAccount.DefaultPassword / SystemAccount.DefaultAdminPassword 为内置的已知默认口令,生产环境务必通过配置覆盖。
{
    "Authentication": {
        "OAuth": {
            "Enabled": true,
            "AccessTokenMinutes": 15,
            "DefaultClientId": "mes-web",
            "Scopes": [ "mes.api", "offline_access" ],
            "RefreshToken": {
                "SlidingMinutes": 720,
                "AbsoluteMinutes": 720,
                "IdleMinutes": 30,
                "RotationGraceSeconds": 10
            },
            "AccessTokenRevocation": {
                "Enabled": false
            },
            "TokenCleanup": {
                "Enabled": true,
                "RetentionDays": 7,
                "IntervalMinutes": 60,
                "BatchSize": 500
            }
        },
        "AuthEntities": {
            "ConnectionString": "Server=127.0.0.1;uid=sa;pwd=password;database=dbname;Trust Server Certificate=true;",
            "DatabaseType": "SqlServer" // 可选(默认 SqlServer),可选值:SqlServer / Oracle / DM / MySql / PostgreSql(大小写不敏感;非法值启动即报错)
        },
        "SystemAccount": {
            "AdminRoleName": "administrator",
            "AdminUserName": "admin",
            "DefaultPassword": "mes123",
            "DefaultAdminPassword": "aspnet2025"
        },
        "ThreeManager": {
            "EnableThreeManager": false,
            "SystemManagerUserName": "110101199001010001",
            "SecurityManagerUserName": "110101199001010002",
            "SecurityAuditorUserName": "110101199001010003",
            "SystemManagerRoleName": "系统管理员",
            "SecurityManagerRoleName": "安全管理员",
            "SecurityAuditorRoleName": "安全审计员",
            "SystemManagerPermissions": "",
            "SecurityManagerPermissions": "",
            "SecurityAuditorPermissions": ""
        },
        "AccessControl": {
            "AllowMultiTerminal": false,
            "SessionTimeoutSeconds": 200,
            "HeartbeatIntervalSeconds": 60,
            "Lockout": {
                "MaxFailedAccessAttempts": 5,
                "DefaultLockoutMinutes": 30,
                "InactiveDaysToLock": 90
            },
            "PasswordPolicy": {
                "ExpiryDays": 180,
                "ReminderDaysBeforeExpiry": 7,
                "RequiredLength": 8,
                "ComplexityRegex": "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).+$",
                "AllowRepeatWithLast": false
            }
        }
    }
}

数据库要求

  • AuthEntities指向的数据库应当全套权限认证体系的数据表
  • 1.2.0 新增:必须存在 AUTH_TOKEN 表(OAuth2 令牌,仅存 SHA-256 哈希)。建表脚本位于 Scripts/OAuth2/:01_postgresql.sql / 02_sqlserver.sql / 03_mysql.sql / 04_oracle.sql / 05_dm.sql,按实际数据库执行一次即可。表上的 USER_NO / APP_NO 外键仅作完整性约束、不级联,删除用户时由应用层先清理其令牌行;执行脚本前 AUTH_USER、AUTH_APPLICATION 必须已存在。
  • AuthEntities指向的数据库应当包含以下序列:
    • AUTH_SEQ_NO:用于生成数据表编号的序列。
  • 数据库中应包含序号生成机制
    • SQL Server:应包含生成Sequence的存储过程和Sequence序列对象
    • Oracle:包含生成Sequence的序列对象即可
    • DM:包含生成Sequence的序列对象即可
    • MySQL:应包含序列表 sequence(NAME/CURRENT_VALUE/INCREMENT)、函数 CurrVal/NextVal/SetVal 及存储过程 aic_sp_get_next_sequence_value
    • PostgreSQL:包含生成Sequence的序列对象即可

使用说明

  • Authentication服务配置:
// 在MesWebApiHostModule中增加对AuthenticationApiModule的依赖:
[DependsOn(
        typeof(AuthenticationApiModule)
        )]
  • 在主工程调用 services.RegisterModules(configuration),AuthenticationApiModule 会自动完成以下注册:
    • IHttpContextAccessor
    • JwtOptions / AuthenticationOptions 配置绑定
    • AuthEntities DbContext(按 DatabaseType 选择 SqlServer / Oracle / DM / MySql / PostgreSql)
    • JWT Bearer 认证
    • 登录 / 账户 / 会话等服务
  • 若不使用模块系统,也可单独调用 services.ConfigureAuthentication(configuration) 完成上述注册(非模块化场景):
  • LoginService需要在主工程内注册扩展登录提供程序,每个提供程序实现 ILoginProvider 并声明 LoginType,直接注册为 ILoginProvider 即可:
services.AddTransient<ILoginProvider, CustomLoginProvider>();
  • 当前项目依赖Redis服务(Redis服务内容参见RT.MesWeb.Redis);

  • 登录会签发 JWT,Jwt 配置节见 RT.MesWeb.Framework 中的 README(SecurityKey 内置默认密钥,未配置也可用)。

OAuth2 令牌接口(1.2.0 起)

登录改为 OAuth2 双令牌:AccessToken(默认 15 分钟)+ RefreshToken(默认 12 小时,闲置 30 分钟失效)。 令牌端点的成功与失败都返回统一响应 ApiResult:HTTP 恒为 200,业务状态在 StatusCode,失败说明在 Message。

端点

方法 路径 说明
POST /api/authorize/token 令牌端点,支持 password 与 refresh_token 两种 grant;仅接受 JSON,字段为 PascalCase
POST /api/authorize/revoke 令牌撤销,无论令牌是否存在均返回成功
POST /api/authorize/login 旧登录接口,仅兼容存量前端、计划停用;新前端请用 /api/authorize/token
POST /api/authorize/logout 旧登出接口,清理会话并撤销该会话的 refresh_token

password grant

curl -X POST http://localhost:5144/api/authorize/token \
  -H "Content-Type: application/json" \
  -d '{"GrantType":"password","Username":"admin","Password":"***","AppId":"mesapp","LoginType":"BS01","DeviceId":"PC-01","ClientId":"mes-web"}'

成功响应:

{
  "Value": {
    "AccessToken": "eyJhbGciOiJIUzI1NiIs...",
    "TokenType": "Bearer",
    "ExpiresIn": 900,
    "RefreshToken": "0f3b9c...",
    "Scope": "mes.api offline_access",
    "SessionId": "7d2f1c8a9b6e4f0d8c3a5b7e9d1f2a4c",
    "IdleTimeout": 1800,
    "HeartbeatInterval": 60,
    "AppId": "mesapp",
    "UserId": "admin",
    "UserName": "管理员",
    "IsAdmin": true,
    "PasswordExpireDays": 172,
    "PasswordExpiringSoon": false
  },
  "StatusCode": 200,
  "Message": ""
}

AppId ~ PasswordExpiringSoon 为用户资料,password 与 refresh_token 两种 grant 都会返回(刷新时按令牌关联用户实时查询)。

失败响应示例:

{ "Value": null, "StatusCode": 403, "Message": "无效的登录请求,用户名不存在!" }

StatusCode 约定:400 请求参数错误、401 刷新令牌失效或客户端无效、403 账号或口令错误、409 多端冲突(Message 为 session_conflict,客户端确认后以 force_login=true 重试)、500 服务端异常。

refresh_token grant

curl -X POST http://localhost:5144/api/authorize/token \
  -H "Content-Type: application/json" \
  -d '{"GrantType":"refresh_token","RefreshToken":"<当前 RefreshToken>","ClientId":"mes-web"}'
  • 每次刷新都会轮换:旧 refresh_token 立即失效并返回新的 refresh_token,客户端必须保存最新的一个。
  • 前端需单飞(single-flight)+ 跨标签页广播(如 BroadcastChannel),避免并发刷新。
  • 旧令牌在 RotationGraceSeconds 窗口内重复使用只会被拒绝;超出窗口后再次使用视为令牌泄露,整个令牌族(family)被撤销。

失效规则

  • 登出、踢人:撤销该会话的 refresh_token。
  • 改密、重置密码、锁定、删除用户:撤销该用户在该应用下的全部 refresh_token。
  • 强制登录挤掉旧会话:撤销该用户在该应用下的历史 refresh_token。
  • 超过 IdleMinutes 未刷新:拒绝刷新并撤销该令牌。
  • 用户被锁定/删除、密码版本(PWD_SET_TIME)变化:刷新时拒绝并撤销令牌族。
  • access_token 无状态,失效依赖自身过期;拒绝列表通过 OAuth:AccessTokenRevocation:Enabled 预留(默认关闭)。

令牌表维护

AUTH_TOKEN 只追加不覆盖(轮换、登出都会留下历史行),库内自带 TokenCleanupService 后台任务:

  • 每 IntervalMinutes(默认 60)执行一次,分批删除 CUR_EXPIRE_TIME 早于「当前时间 − RetentionDays」的行;
  • 默认保留 7 天,便于排查问题;RetentionDays=0 表示过期即删;
  • 按 BatchSize(默认 500)分批删除,避免一次性删除造成长事务与锁等待;
  • 多个实例同时运行是安全的(删除幂等),Enabled=false 可关闭。

在线状态(1.2.0 起)

带 Bearer 的业务请求执行成功后,SessionActivityFilter 会自动触达一次在线会话;同一会话 60 秒内最多触达一次,因此前端无需再定时调用 /api/authorize/heartbeat(接口仍保留,兼容旧前端)。

  • 触达只影响在线状态展示与多端登录冲突检测,不改变 refresh_token 寿命;
  • 请求失败(抛异常或 HTTP ≥ 400)不触达;会话已被踢下线时不重建;
  • 部署注意:Authentication:AccessControl:SessionTimeoutSeconds 应不小于触达间隔的 2~3 倍(默认 200s vs 60s,安全)。

改造说明

认证接口契约、前端对接流程与遗留任务见源码仓库中的 认证接口说明.md(面向前端开发,只描述当前体系;该文档不随 NuGet 包发布)。

  • Authentication有授权检查,需要在主工程内启动授权服务(授权配置参见RT.MesWeb.Framework中的README):
MesLicenseChecker.Current.Start(configuration, hostEnvironment.ContentRootPath, logger);
  • 当前项目已经启用多语言支持,需要在主工程内注册多语言资源:
// 在应用程序构建前:
services.AddLocalization(options => options.ResourcesPath = "");
services.Configure<RequestLocalizationOptions>(options =>
{
    var supportedCultures = new[]
    {
        new CultureInfo("zh-CN"),  // 中文简体
        new CultureInfo("en-US"),  // 英文
    };

    // 设置支持的语言列表
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;
    // 默认语言(无语言标识时使用)
    options.DefaultRequestCulture = new RequestCulture("zh-CN");
    // 优先级:URL参数 > Cookie > 请求头
    options.RequestCultureProviders.Insert(0, new QueryStringRequestCultureProvider());
});
// 在应用程序构建后:
app.UseRequestLocalization(app.Services.GetRequiredService<IOptions<RequestLocalizationOptions>>().Value);
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.0 104 11/2/2026
1.1.1 178 7/15/2026
1.1.0 133 7/3/2026
1.0.3 138 6/11/2026
1.0.2 132 5/26/2026
1.0.1 142 5/8/2026
1.0.0 138 4/27/2026