-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
131 lines (112 loc) · 4.49 KB
/
Copy pathProgram.cs
File metadata and controls
131 lines (112 loc) · 4.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
using JuggleNet6.Backend.Domain.Engine;
using JuggleNet6.Backend.Infrastructure.Persistence;
using JuggleNet6.Backend.Services.Flow;
using JuggleNet6.Backend.Services.Impl;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using System.Text;
using System.Text.Json;
var builder = WebApplication.CreateBuilder(args);
// ==================== 服务注册 ====================
// JSON 配置(camelCase 输出)
builder.Services.AddControllers().AddJsonOptions(opts =>
{
opts.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
opts.JsonSerializerOptions.DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull;
});
// SQLite + EF Core
var dbPath = Path.Combine(Directory.GetCurrentDirectory(), "juggle.db");
builder.Services.AddDbContext<JuggleDbContext>(opts =>
opts.UseSqlite($"Data Source={dbPath}"));
// JWT 认证
var jwtKey = builder.Configuration["Jwt:Key"] ?? "JuggleNet6SecretKey2026!";
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(opts =>
{
opts.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey)),
ValidateIssuer = true,
ValidIssuer = "JuggleNet6",
ValidateAudience = true,
ValidAudience = "JuggleNet6",
ValidateLifetime = true
};
// 统一返回 JSON 格式的 401,方便前端处理
opts.Events = new Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerEvents
{
OnChallenge = async ctx =>
{
ctx.HandleResponse();
ctx.Response.StatusCode = 401;
ctx.Response.ContentType = "application/json";
await ctx.Response.WriteAsync(
System.Text.Json.JsonSerializer.Serialize(
new { code = 401, message = "未授权,请先登录", data = (object?)null },
new System.Text.Json.JsonSerializerOptions { PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase }
));
}
};
});
builder.Services.AddAuthorization();
// HttpClient(供流程引擎和 API 调试使用)
builder.Services.AddHttpClient();
// 流程引擎(Scoped,因依赖 HttpClientFactory)
builder.Services.AddScoped<FlowEngine>();
// ── 业务 Service 层 ──────────────────────────────────────────────
builder.Services.AddScoped<FlowExecutionService>(); // 流程执行核心(数据源、静态变量、日志)
builder.Services.AddScoped<DataSourceService>(); // 数据源连接字符串构建 + 连接测试
builder.Services.AddScoped<JwtService>(); // JWT Token 签发
// Swagger
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Juggle Net8 API", Version = "v1" });
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header. Format: Bearer {token}",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer"
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } },
Array.Empty<string>()
}
});
});
// CORS(开发环境允许前端跨域)
builder.Services.AddCors(opts =>
{
opts.AddDefaultPolicy(policy =>
policy.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
});
// ==================== 应用构建 ====================
var app = builder.Build();
// 自动迁移数据库
using (var scope = app.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<JuggleDbContext>();
db.Database.EnsureCreated();
}
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseCors();
app.UseAuthentication();
app.UseAuthorization();
// 前端静态文件(生产环境)
app.UseDefaultFiles();
app.UseStaticFiles();
app.MapControllers();
// SPA fallback(前端路由)
app.MapFallbackToFile("index.html");
app.Run();