添加项目文件。
This commit is contained in:
1 parent
6a017c9547
commit
58abbb5b4f
86 files changed
+8729
No files matched your search
@@ -0,0 +1,112 @@
|
||||
using Asp.Versioning;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using StoreHub.Framework.Commons;
|
||||
using StoreHub.Framework.Security;
|
||||
using StoreHub.Services;
|
||||
using StoreHub.Services.Dtos;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace StoreHub.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[ApiVersion("1.0")]
|
||||
[Route("api/v{version:apiVersion}/[controller]/[action]")]
|
||||
public class AuthController : ControllerBase
|
||||
{
|
||||
private readonly IUserService _userService;
|
||||
private readonly ITokenService _tokenService;
|
||||
private readonly ICurrentUser _currentUser;
|
||||
private readonly IOnlineUserStore _onlineUserStore;
|
||||
|
||||
public AuthController(IUserService userService, ITokenService tokenService, ICurrentUser currentUser, IOnlineUserStore onlineUserStore)
|
||||
{
|
||||
_userService = userService;
|
||||
_tokenService = tokenService;
|
||||
_currentUser = currentUser;
|
||||
_onlineUserStore = onlineUserStore;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 登录:校验用户名/密码,签发 JWT(单点登录:同用户的新登录会使旧令牌失效)
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
public async Task<ApiResult<object?>> Login([FromBody] LoginRequest request)
|
||||
{
|
||||
if (request is null || string.IsNullOrWhiteSpace(request.UserName) || string.IsNullOrWhiteSpace(request.Password))
|
||||
{
|
||||
return ApiResult.Error("用户名或密码不能为空", 400);
|
||||
}
|
||||
|
||||
UserDto? user = await _userService.LoginAsync(request.UserName, request.Password);
|
||||
if (user is null)
|
||||
{
|
||||
return ApiResult.Error("用户名或密码错误", 401);
|
||||
}
|
||||
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new(JwtClaimTypes.UserId, user.Id.ToString()),
|
||||
new(JwtClaimTypes.UserName, user.UserName),
|
||||
new(JwtClaimTypes.NickName, user.NickName),
|
||||
};
|
||||
|
||||
TokenResult token = _tokenService.CreateToken(claims);
|
||||
return ApiResult.Success<object?>(token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 退出登录:销毁当前用户的服务端在线会话,令牌立即失效
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
[Authorize]
|
||||
public ApiResult<object?> Logout()
|
||||
{
|
||||
if (_currentUser.Id is int userId)
|
||||
{
|
||||
_onlineUserStore.SignOut(userId);
|
||||
}
|
||||
|
||||
return ApiResult.Success<object?>(null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前登录用户信息(需携带 Bearer Token)
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
public ApiResult<object?> Me()
|
||||
{
|
||||
return ApiResult.Success<object?>(new
|
||||
{
|
||||
UserId = _currentUser.Id,
|
||||
UserName = _currentUser.UserName,
|
||||
NickName = _currentUser.NickName,
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在线人员列表(需携带 Bearer Token)
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
public ApiResult<object?> OnlineUsers()
|
||||
{
|
||||
IReadOnlyList<OnlineUserInfo> users = _onlineUserStore.GetOnlineUsers();
|
||||
return ApiResult.Success<object?>(new
|
||||
{
|
||||
Count = users.Count,
|
||||
Users = users,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class LoginRequest
|
||||
{
|
||||
public string UserName { get; set; } = string.Empty;
|
||||
|
||||
public string Password { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using Asp.Versioning;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using StoreHub.Framework.Repositorys;
|
||||
using System.ComponentModel;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StoreHub.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Description("测试温度")]
|
||||
[ApiVersion("1.0")]
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
public class UserController : ControllerBase
|
||||
{
|
||||
private readonly IUserRepository _userRepository;
|
||||
|
||||
public UserController(IUserRepository userRepository)
|
||||
{
|
||||
_userRepository = userRepository;
|
||||
}
|
||||
[HttpGet]
|
||||
public string GetUser()
|
||||
{
|
||||
return JsonSerializer.Serialize(_userRepository.Select.First());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using Asp.Versioning;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using StoreHub.Framework.Commons;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace StoreHub.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Description("测试温度")]
|
||||
[ApiVersion("1.0")]
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
public class WeatherForecastController : ControllerBase
|
||||
{
|
||||
private static readonly string[] Summaries =
|
||||
[
|
||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||
];
|
||||
|
||||
[HttpGet(Name = "GetWeatherForecast")]
|
||||
public ApiResult<IEnumerable<WeatherForecast>> Get()
|
||||
{
|
||||
IEnumerable<WeatherForecast> data = Enumerable.Range(1, 5).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();
|
||||
|
||||
return ApiResult.Success(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Asp.Versioning;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using StoreHub.Framework.Commons;
|
||||
|
||||
namespace StoreHub.Controllers.v2
|
||||
{
|
||||
[ApiController]
|
||||
[ApiVersion("2.0")]
|
||||
[Route("api/v{version:apiVersion}/[controller]")]
|
||||
public class WeatherForecastController : ControllerBase
|
||||
{
|
||||
private static readonly string[] Summaries =
|
||||
[
|
||||
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
|
||||
];
|
||||
|
||||
[HttpGet(Name = "GetWeatherForecastV2")]
|
||||
public ApiResult<IEnumerable<WeatherForecastV2>> Get()
|
||||
{
|
||||
IEnumerable<WeatherForecastV2> data = Enumerable.Range(1, 10).Select(index => new WeatherForecastV2
|
||||
{
|
||||
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
||||
TemperatureC = Random.Shared.Next(-20, 55),
|
||||
FeelsLikeC = Random.Shared.Next(-20, 55),
|
||||
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
|
||||
})
|
||||
.ToArray();
|
||||
|
||||
return ApiResult.Success(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
using Asp.Versioning;
|
||||
using Scalar.AspNetCore;
|
||||
using StoreHub.Framework.DependencyInjection;
|
||||
|
||||
public partial class Program
|
||||
{
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// IOC 注册:自动注册 ISingletonDependency / IScopedDependency / ITransientDependency,并执行所有 IStartup(实现见 StoreHub.Framework)
|
||||
builder.Services.AddStoreHub();
|
||||
builder.Services.AddFreeSqlDB();
|
||||
// JWT 验证:注册 JwtBearer 认证 + 令牌服务 + OpenAPI Bearer 安全方案(配置节 Jwt)
|
||||
builder.Services.AddStoreHubJwt(builder.Configuration);
|
||||
// Add services to the container.
|
||||
|
||||
builder.Services.AddControllers();
|
||||
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
|
||||
builder.Services.AddApiVersioning(options =>
|
||||
{
|
||||
options.DefaultApiVersion = new ApiVersion(1, 0);
|
||||
options.ReportApiVersions = true;
|
||||
options.ApiVersionReader = new UrlSegmentApiVersionReader();
|
||||
}).AddMvc().AddApiExplorer(options =>
|
||||
{
|
||||
options.GroupNameFormat = "'v'V";
|
||||
options.SubstituteApiVersionInUrl = true;
|
||||
}).AddOpenApi();
|
||||
|
||||
#region DB
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.MapOpenApi().WithDocumentPerVersion();
|
||||
app.MapScalarApiReference(options =>
|
||||
{
|
||||
|
||||
options.Title = "商铺管理API V1";
|
||||
options.AddDocuments(new[] { "v1", "v2" });
|
||||
});
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
|
||||
app.UseAuthentication();
|
||||
|
||||
app.UseAuthorization();
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "scalar/v1",
|
||||
"applicationUrl": "http://localhost:5295",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "scalar/v1",
|
||||
"applicationUrl": "https://localhost:7241;http://localhost:5295",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.10" />
|
||||
<PackageReference Include="Scalar.AspNetCore" Version="2.16.18" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\StoreHub.Framework\StoreHub.Framework.csproj" />
|
||||
<ProjectReference Include="..\StoreHub.KJDWebService\StoreHub.KJDWebService.csproj" />
|
||||
<ProjectReference Include="..\StoreHub.Services\StoreHub.Services.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,47 @@
|
||||
@StoreHub_HostAddress = http://localhost:5295
|
||||
|
||||
# ============ 认证(JWT) ============
|
||||
|
||||
### 登录:返回 accessToken(单点登录,同用户新登录会使旧 token 失效)
|
||||
# @name login
|
||||
POST {{StoreHub_HostAddress}}/api/v1/Auth/Login
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"userName": "18990011234",
|
||||
"password": "18990011234"
|
||||
}
|
||||
|
||||
### 获取当前登录用户信息(需携带 Bearer Token,先执行上面的 login)
|
||||
GET {{StoreHub_HostAddress}}/api/v1/Auth/Me
|
||||
Authorization: Bearer {{login.response.body.$.data.token}}
|
||||
|
||||
### 退出登录:销毁服务端会话,token 立即失效
|
||||
POST {{StoreHub_HostAddress}}/api/v1/Auth/Logout
|
||||
Authorization: Bearer {{login.response.body.$.data.token}}
|
||||
|
||||
### 在线人员列表(需携带 Bearer Token)
|
||||
GET {{StoreHub_HostAddress}}/api/v1/Auth/OnlineUsers
|
||||
Authorization: Bearer {{login.response.body.$.data.token}}
|
||||
|
||||
# ============ 示例接口 ============
|
||||
|
||||
### 模板自带的 WeatherForecast
|
||||
GET {{StoreHub_HostAddress}}/api/v1/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
POST {{StoreHub_HostAddress}}/api/v1/Auth/Login
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
//LoginRequest
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
POST {{StoreHub_HostAddress}}/api/v1/Auth/Login
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
//LoginRequest
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace StoreHub
|
||||
{
|
||||
public class WeatherForecast
|
||||
{
|
||||
public DateOnly Date { get; set; }
|
||||
|
||||
public int TemperatureC { get; set; }
|
||||
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
|
||||
public string? Summary { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace StoreHub
|
||||
{
|
||||
public class WeatherForecastV2
|
||||
{
|
||||
public DateOnly Date { get; set; }
|
||||
|
||||
public int TemperatureC { get; set; }
|
||||
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
|
||||
public int FeelsLikeC { get; set; }
|
||||
|
||||
public string? Summary { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Server=localhost;Port=3306;Database=erp;Uid=root;Pwd=123456;",
|
||||
"UserConnection": "Server=localhost;Port=3306;Database=wxxd;Uid=root;Pwd=123456;",
|
||||
"KJDConnection": "Server=localhost;Port=3306;Database=mysql;Uid=root;Pwd=123456;"
|
||||
},
|
||||
"Jwt": {
|
||||
"Issuer": "StoreHub",
|
||||
"Audience": "StoreHub.Client",
|
||||
"SigningKey": "StoreHub--Smxf8DtV8a5dFdaCVCXtFfWbmMRfw53ectEjr8JvhUjGpPP7fuBdRn",
|
||||
"ExpiresMinutes": 120,
|
||||
"ClockSkewMinutes": 5,
|
||||
"ValidateIssuer": true,
|
||||
"ValidateAudience": true,
|
||||
"ValidateLifetime": true
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
Reference in new issue
Block a user