diff --git a/CubeDemo/CubeDemo.csproj b/CubeDemo/CubeDemo.csproj
index f5481577..fb5c322b 100644
--- a/CubeDemo/CubeDemo.csproj
+++ b/CubeDemo/CubeDemo.csproj
@@ -5,8 +5,8 @@
魔方WebApi
魔方前后端分离版本的后端WebApi
新生命开发团队
- ©2002-2023 NewLife
- 5.5
+ ©2002-2024 NewLife
+ 6.1
$([System.DateTime]::Now.ToString(`yyyy.MMdd`))
$(VersionPrefix).$(VersionSuffix)
$(Version)
diff --git a/NewLife.Cube.Swagger/SwaggerConfigureOptions.cs b/NewLife.Cube.Swagger/SwaggerConfigureOptions.cs
index f147288b..ed9e1bed 100644
--- a/NewLife.Cube.Swagger/SwaggerConfigureOptions.cs
+++ b/NewLife.Cube.Swagger/SwaggerConfigureOptions.cs
@@ -4,6 +4,7 @@
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
+using NewLife.Reflection;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace NewLife.Cube.Swagger;
@@ -34,10 +35,13 @@ public void Configure(SwaggerGenOptions options)
var area = controller.ControllerTypeInfo.GetCustomAttribute();
if (area != null)
{
+ var type = area.GetType();
+ var asm = AssemblyX.Create(type.Assembly);
info = new OpenApiInfo
{
- Title = area.GetType().GetDisplayName(),
- Description = area.GetType().GetDescription()?.Replace("\n", "
")
+ Title = type.GetDisplayName(),
+ Description = type.GetDescription()?.Replace("\n", "
"),
+ Version = asm.FileVersion,
};
break;
}
diff --git a/NewLife.Cube.Swagger/SwaggerService.cs b/NewLife.Cube.Swagger/SwaggerService.cs
index 2ea9dd62..05ba76a5 100644
--- a/NewLife.Cube.Swagger/SwaggerService.cs
+++ b/NewLife.Cube.Swagger/SwaggerService.cs
@@ -3,6 +3,7 @@
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using NewLife.Cube.Entity;
+using NewLife.Reflection;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace NewLife.Cube.Swagger;
@@ -26,7 +27,8 @@ public static IServiceCollection AddCubeSwagger(this IServiceCollection services
var xml = "NewLife.Cube.xml".GetFullPath();
if (File.Exists(xml)) options.IncludeXmlComments(xml, true);
- options.SwaggerDoc("v1", new OpenApiInfo { Title = "第三代魔方", Description = "第三代魔方WebApi接口,用于前后端分离。" });
+ var asm = AssemblyX.Entry;
+ options.SwaggerDoc("v1", new OpenApiInfo { Title = "第三代魔方", Description = "第三代魔方WebApi接口,用于前后端分离。", Version = asm.FileVersion });
//options.SwaggerDoc("Basic", new OpenApiInfo { Version = "basic", Title = "基础模块" });
//options.SwaggerDoc("Admin", new OpenApiInfo { Version = "admin", Title = "系统管理" });
//options.SwaggerDoc("Cube", new OpenApiInfo { Version = "cube", Title = "魔方管理" });
@@ -48,8 +50,8 @@ public static IServiceCollection AddCubeSwagger(this IServiceCollection services
var cfg = oauthConfigs[0];
var flow = new OpenApiOAuthFlow
{
- AuthorizationUrl = new Uri(cfg.Server),
- TokenUrl = new Uri(!cfg.AccessServer.IsNullOrEmpty() ? cfg.AccessServer : cfg.Server),
+ AuthorizationUrl = new Uri(cfg.Server + "/authorize"),
+ TokenUrl = new Uri((!cfg.AccessServer.IsNullOrEmpty() ? cfg.AccessServer : cfg.Server) + "/access_token"),
//Scopes = new Dictionary
//{
// { "api1", "Access to API #1" }
@@ -58,10 +60,17 @@ public static IServiceCollection AddCubeSwagger(this IServiceCollection services
options.AddSecurityDefinition("OAuth2", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
+ In = ParameterLocation.Query,
Flows = new OpenApiOAuthFlows { AuthorizationCode = flow }
});
- //options.OperationFilter();
+ // 声明一个Scheme,注意下面的Id要和上面AddSecurityDefinition中的参数name一致
+ var scheme = new OpenApiSecurityScheme()
+ {
+ Reference = new OpenApiReference() { Type = ReferenceType.SecurityScheme, Id = "OAuth2" }
+ };
+ // 注册全局认证(所有的接口都可以使用认证)
+ options.AddSecurityRequirement(new OpenApiSecurityRequirement() { [scheme] = [] });
}
else
{
@@ -72,7 +81,7 @@ public static IServiceCollection AddCubeSwagger(this IServiceCollection services
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
- Scheme = "bearer"
+ Scheme = "Bearer"
});
// 声明一个Scheme,注意下面的Id要和上面AddSecurityDefinition中的参数name一致
var scheme = new OpenApiSecurityScheme()
@@ -96,6 +105,9 @@ public static IApplicationBuilder UseCubeSwagger(this IApplicationBuilder app)
//app.UseSwaggerUI();
app.UseSwaggerUI(options =>
{
+ var asm = AssemblyX.Entry;
+ options.DocumentTitle = !asm.Title.IsNullOrEmpty() ? asm.Title : "魔方Web开发平台";
+
//options.SwaggerEndpoint("/swagger/Basic/swagger.json", "Basic");
//options.SwaggerEndpoint("/swagger/Admin/swagger.json", "Admin");
//options.SwaggerEndpoint("/swagger/Cube/swagger.json", "Cube");
diff --git a/NewLife.Cube/Areas/Admin/AdminAreaRegistration.cs b/NewLife.Cube/Areas/Admin/AdminAreaRegistration.cs
index 54d1e073..555157a4 100644
--- a/NewLife.Cube/Areas/Admin/AdminAreaRegistration.cs
+++ b/NewLife.Cube/Areas/Admin/AdminAreaRegistration.cs
@@ -5,7 +5,7 @@ namespace NewLife.Cube.Areas.Admin;
/// 权限管理区域注册
[DisplayName("系统管理")]
[Description("""
- 核心功能:用户、角色、菜单,构成基本权限体系。
+ 核心功能:用户、角色、菜单,构成基本权限体系。
核心配置:基本设置、系统设置、魔方设置、数据中间件。
OAuth功能:OAuth配置微信钉钉等多个第三方SSO登录。
安全功能:审计日志、访问规则,保障系统安全。
diff --git a/NewLife.Cube/Controllers/CubeController.cs b/NewLife.Cube/Controllers/CubeController.cs
index b9c04d87..3f66905e 100644
--- a/NewLife.Cube/Controllers/CubeController.cs
+++ b/NewLife.Cube/Controllers/CubeController.cs
@@ -21,7 +21,7 @@ namespace NewLife.Cube.Controllers;
[Description("""
魔方向前端控件提供的一些常用接口,例如用户查询与头像获取等。
""")]
-[ApiExplorerSettings(GroupName = "Basic")]
+//[ApiExplorerSettings(GroupName = "Cube")]
[Route("[controller]/[action]")]
public class CubeController : ControllerBaseX
{
diff --git a/NewLife.Cube/Controllers/SsoController.cs b/NewLife.Cube/Controllers/SsoController.cs
index c65f8426..c143e121 100644
--- a/NewLife.Cube/Controllers/SsoController.cs
+++ b/NewLife.Cube/Controllers/SsoController.cs
@@ -53,7 +53,7 @@ namespace NewLife.Cube.Controllers;
魔方支持接入微信钉钉等多个第三方OAuth2.0服务。
魔方自身也可以作为OAuth2.0服务端,支持密码式、凭证式、刷新令牌等多种授权模式。
""")]
-[ApiExplorerSettings(GroupName = "Basic")]
+//[ApiExplorerSettings(GroupName = "Cube")]
[Route("[controller]/[action]")]
public class SsoController : ControllerBaseX
{
@@ -479,6 +479,7 @@ public virtual ActionResult Auth2(String id)
///
[AllowAnonymous]
[HttpGet]
+ [HttpPost]
public virtual ActionResult Access_Token(String client_id, String client_secret, String code, String grant_type = null)
{
if (client_id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(client_id));
@@ -534,6 +535,7 @@ public virtual ActionResult Access_Token(String client_id, String client_secret,
///
[AllowAnonymous]
[HttpGet]
+ [HttpPost]
public new virtual ActionResult Token(String client_id, String client_secret, String username, String password, String refresh_token, String grant_type = null)
{
if (client_id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(client_id));
@@ -600,6 +602,7 @@ public virtual ActionResult Access_Token(String client_id, String client_secret,
///
[AllowAnonymous]
[HttpGet]
+ [HttpPost]
public virtual ActionResult PasswordToken([FromBody] SsoTokenModel model)
{
if (model.client_id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(model.client_id));
@@ -689,6 +692,7 @@ public virtual ActionResult UserInfo(String access_token)
///
[AllowAnonymous]
[HttpGet]
+ [HttpPost]
public virtual ActionResult Refresh_Token(String client_id, String grant_type, String refresh_token)
{
if (client_id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(client_id));
@@ -810,6 +814,7 @@ public ActionResult Verify(String access_token, String redirect_uri)
///
[AllowAnonymous]
[HttpGet]
+ [HttpPost]
public virtual ActionResult UserAuth([FromBody] SsoTokenModel model)
{
var client_id = model.client_id;
diff --git a/NewLife.Cube/Web/Models/SsoTokenModel.cs b/NewLife.Cube/Web/Models/SsoTokenModel.cs
index 774e3ddc..0fe7aebe 100644
--- a/NewLife.Cube/Web/Models/SsoTokenModel.cs
+++ b/NewLife.Cube/Web/Models/SsoTokenModel.cs
@@ -1,24 +1,20 @@
-using System;
-using System.Runtime.Serialization;
+namespace NewLife.Cube.Web.Models;
-namespace NewLife.Cube.Web.Models
+/// Sso令牌模型
+public class SsoTokenModel
{
- /// Sso令牌模型
- public class SsoTokenModel
- {
- /// 应用标识
- public String client_id { get; set; }
+ /// 应用标识
+ public String client_id { get; set; }
- /// 应用密钥
- public String client_secret { get; set; }
+ /// 应用密钥
+ public String client_secret { get; set; }
- /// 用户名。可以是设备编码等唯一使用者标识
- public String UserName { get; set; }
+ /// 用户名。可以是设备编码等唯一使用者标识
+ public String UserName { get; set; }
- /// 密码
- public String Password { get; set; }
+ /// 密码
+ public String Password { get; set; }
- /// 授权类型
- public String grant_type { get; set; }
- }
+ /// 授权类型
+ public String grant_type { get; set; }
}
\ No newline at end of file
diff --git a/NewLife.CubeNC/Controllers/SsoController.cs b/NewLife.CubeNC/Controllers/SsoController.cs
index c7b52481..bd16dca3 100644
--- a/NewLife.CubeNC/Controllers/SsoController.cs
+++ b/NewLife.CubeNC/Controllers/SsoController.cs
@@ -476,6 +476,8 @@ public virtual ActionResult Auth2(String id)
/// 授权类型
///
[AllowAnonymous]
+ [HttpGet]
+ [HttpPost]
public virtual ActionResult Access_Token(String client_id, String client_secret, String code, String grant_type = null)
{
if (client_id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(client_id));
@@ -530,6 +532,8 @@ public virtual ActionResult Access_Token(String client_id, String client_secret,
/// 授权类型
///
[AllowAnonymous]
+ [HttpGet]
+ [HttpPost]
public virtual ActionResult Token(String client_id, String client_secret, String username, String password, String refresh_token, String grant_type = null)
{
if (client_id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(client_id));
@@ -595,6 +599,8 @@ public virtual ActionResult Token(String client_id, String client_secret, String
/// 请求模型
///
[AllowAnonymous]
+ [HttpGet]
+ [HttpPost]
public virtual ActionResult PasswordToken([FromBody] SsoTokenModel model)
{
if (model.client_id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(model.client_id));
@@ -682,6 +688,8 @@ public virtual ActionResult UserInfo(String access_token)
/// 刷新令牌
///
[AllowAnonymous]
+ [HttpGet]
+ [HttpPost]
public virtual ActionResult Refresh_Token(String client_id, String grant_type, String refresh_token)
{
if (client_id.IsNullOrEmpty()) throw new ArgumentNullException(nameof(client_id));
@@ -799,6 +807,8 @@ public ActionResult Verify(String access_token, String redirect_uri)
/// 令牌模型
///
[AllowAnonymous]
+ [HttpGet]
+ [HttpPost]
public virtual ActionResult UserAuth([FromBody] SsoTokenModel model)
{
var client_id = model.client_id;