diff --git a/Controllers/AccountController.cs b/Controllers/AccountController.cs index d8ee7cb..727e4a0 100644 --- a/Controllers/AccountController.cs +++ b/Controllers/AccountController.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; namespace Fengling.AuthService.Controllers; @@ -13,15 +14,18 @@ public class AccountController : Controller { private readonly UserManager _userManager; private readonly SignInManager _signInManager; + private readonly ApplicationDbContext _dbContext; private readonly ILogger _logger; public AccountController( UserManager userManager, SignInManager signInManager, + ApplicationDbContext dbContext, ILogger logger) { _userManager = userManager; _signInManager = signInManager; + _dbContext = dbContext; _logger = logger; } @@ -79,12 +83,22 @@ public class AccountController : Controller return View(model); } + var defaultTenant = await _dbContext.Tenants + .FirstOrDefaultAsync(t => t.TenantId == "default"); + + if (defaultTenant == null) + { + ModelState.AddModelError(string.Empty, "系统配置错误:未找到默认租户"); + return View(model); + } + var user = new ApplicationUser { UserName = model.Username, Email = model.Email, NormalizedUserName = model.Username.ToUpper(), - NormalizedEmail = model.Email.ToUpper() + NormalizedEmail = model.Email.ToUpper(), + TenantInfo = new TenantInfo(defaultTenant.Id, defaultTenant.TenantId, defaultTenant.Name) }; var result = await _userManager.CreateAsync(user, model.Password); diff --git a/Controllers/OAuthClientsController.cs b/Controllers/OAuthClientsController.cs index a98e39d..86a4964 100644 --- a/Controllers/OAuthClientsController.cs +++ b/Controllers/OAuthClientsController.cs @@ -3,7 +3,9 @@ using Fengling.AuthService.Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; +using OpenIddict.Abstractions; using System.Security.Claims; +using System.Security.Cryptography; namespace Fengling.AuthService.Controllers; @@ -13,13 +15,16 @@ namespace Fengling.AuthService.Controllers; public class OAuthClientsController : ControllerBase { private readonly ApplicationDbContext _context; + private readonly IOpenIddictApplicationManager _applicationManager; private readonly ILogger _logger; public OAuthClientsController( ApplicationDbContext context, + IOpenIddictApplicationManager applicationManager, ILogger logger) { _context = context; + _applicationManager = applicationManager; _logger = logger; } @@ -69,6 +74,7 @@ public class OAuthClientsController : ControllerBase status = c.Status, description = c.Description, createdAt = c.CreatedAt, + updatedAt = c.UpdatedAt, }); return Ok(new @@ -80,6 +86,46 @@ public class OAuthClientsController : ControllerBase }); } + [HttpGet("options")] + public ActionResult GetClientOptions() + { + return Ok(new + { + clientTypes = new[] + { + new { value = "public", label = "Public (SPA, Mobile App)" }, + new { value = "confidential", label = "Confidential (Server-side)" } + }, + consentTypes = new[] + { + new { value = "implicit", label = "Implicit" }, + new { value = "explicit", label = "Explicit" }, + new { value = "system", label = "System (Pre-authorized)" } + }, + grantTypes = new[] + { + new { value = "authorization_code", label = "Authorization Code" }, + new { value = "client_credentials", label = "Client Credentials" }, + new { value = "refresh_token", label = "Refresh Token" }, + new { value = "password", label = "Resource Owner Password Credentials" } + }, + scopes = new[] + { + new { value = "openid", label = "OpenID Connect" }, + new { value = "profile", label = "Profile" }, + new { value = "email", label = "Email" }, + new { value = "api", label = "API Access" }, + new { value = "offline_access", label = "Offline Access" } + }, + statuses = new[] + { + new { value = "active", label = "Active" }, + new { value = "inactive", label = "Inactive" }, + new { value = "suspended", label = "Suspended" } + } + }); + } + [HttpGet("{id}")] public async Task> GetClient(long id) { @@ -103,45 +149,62 @@ public class OAuthClientsController : ControllerBase status = client.Status, description = client.Description, createdAt = client.CreatedAt, - }); - } - - [HttpGet("{id}/secret")] - public async Task> GetClientSecret(long id) - { - var client = await _context.OAuthApplications.FindAsync(id); - if (client == null) - { - return NotFound(); - } - - return Ok(new - { - clientId = client.ClientId, - clientSecret = client.ClientSecret, + updatedAt = client.UpdatedAt, }); } [HttpPost] - public async Task> CreateClient(CreateOAuthClientDto dto) + public async Task> CreateClient([FromBody] CreateOAuthClientDto dto) { - if (await _context.OAuthApplications.AnyAsync(c => c.ClientId == dto.ClientId)) + var existingClient = await _context.OAuthApplications.FirstOrDefaultAsync(c => c.ClientId == dto.ClientId); + if (existingClient != null) { - return BadRequest(new { message = "Client ID 已存在" }); + return BadRequest(new { message = "Client ID 已存在", clientId = dto.ClientId }); } + var clientSecret = string.IsNullOrEmpty(dto.ClientSecret) ? GenerateSecureSecret() : dto.ClientSecret; + + var descriptor = new OpenIddictApplicationDescriptor + { + ClientId = dto.ClientId, + ClientSecret = clientSecret, + DisplayName = dto.DisplayName + }; + + foreach (var uri in (dto.RedirectUris ?? Array.Empty()).Where(u => Uri.TryCreate(u, UriKind.Absolute, out _))) + { + descriptor.RedirectUris.Add(new Uri(uri)); + } + + foreach (var uri in (dto.PostLogoutRedirectUris ?? Array.Empty()).Where(u => Uri.TryCreate(u, UriKind.Absolute, out _))) + { + descriptor.PostLogoutRedirectUris.Add(new Uri(uri)); + } + + foreach (var grantType in dto.GrantTypes ?? Array.Empty()) + { + descriptor.Permissions.Add(grantType); + } + + foreach (var scope in dto.Scopes ?? Array.Empty()) + { + descriptor.Permissions.Add(scope); + } + + await _applicationManager.CreateAsync(descriptor); + var client = new OAuthApplication { ClientId = dto.ClientId, - ClientSecret = dto.ClientSecret, + ClientSecret = clientSecret, DisplayName = dto.DisplayName, - RedirectUris = dto.RedirectUris, - PostLogoutRedirectUris = dto.PostLogoutRedirectUris, - Scopes = dto.Scopes, - GrantTypes = dto.GrantTypes, - ClientType = dto.ClientType, - ConsentType = dto.ConsentType, - Status = dto.Status, + RedirectUris = dto.RedirectUris ?? Array.Empty(), + PostLogoutRedirectUris = dto.PostLogoutRedirectUris ?? Array.Empty(), + Scopes = dto.Scopes ?? new[] { "openid", "profile", "email", "api" }, + GrantTypes = dto.GrantTypes ?? new[] { "authorization_code", "refresh_token" }, + ClientType = dto.ClientType ?? "confidential", + ConsentType = dto.ConsentType ?? "explicit", + Status = dto.Status ?? "active", Description = dto.Description, CreatedAt = DateTime.UtcNow, }; @@ -151,11 +214,19 @@ public class OAuthClientsController : ControllerBase await CreateAuditLog("oauth", "create", "OAuthClient", client.Id, client.DisplayName, null, SerializeToJson(dto)); - return CreatedAtAction(nameof(GetClient), new { id = client.Id }, client); + return CreatedAtAction(nameof(GetClient), new { id = client.Id }, new + { + client.Id, + client.ClientId, + client.ClientSecret, + client.DisplayName, + client.Status, + client.CreatedAt + }); } - [HttpPut("{id}")] - public async Task UpdateClient(long id, UpdateOAuthClientDto dto) + [HttpPost("{id}/generate-secret")] + public async Task> GenerateSecret(long id) { var client = await _context.OAuthApplications.FindAsync(id); if (client == null) @@ -163,21 +234,123 @@ public class OAuthClientsController : ControllerBase return NotFound(); } - var oldValue = SerializeToJson(client); + var newSecret = GenerateSecureSecret(); + client.ClientSecret = newSecret; + client.UpdatedAt = DateTime.UtcNow; - client.DisplayName = dto.DisplayName; - client.RedirectUris = dto.RedirectUris; - client.PostLogoutRedirectUris = dto.PostLogoutRedirectUris; - client.Scopes = dto.Scopes; - client.GrantTypes = dto.GrantTypes; - client.ClientType = dto.ClientType; - client.ConsentType = dto.ConsentType; - client.Status = dto.Status; - client.Description = dto.Description; + var application = await _applicationManager.FindByClientIdAsync(client.ClientId); + if (application != null) + { + var descriptor = new OpenIddictApplicationDescriptor + { + ClientId = client.ClientId, + ClientSecret = newSecret, + DisplayName = client.DisplayName + }; + + await _applicationManager.UpdateAsync(application, descriptor); + } await _context.SaveChangesAsync(); - await CreateAuditLog("oauth", "update", "OAuthClient", client.Id, client.DisplayName, oldValue, SerializeToJson(client)); + await CreateAuditLog("oauth", "generate_secret", "OAuthClient", client.Id, client.DisplayName, "[REDACTED]", "[REDACTED]"); + + return Ok(new + { + clientId = client.ClientId, + clientSecret = newSecret, + message = "新密钥已生成,请妥善保管,刷新后将无法再次查看" + }); + } + + [HttpPost("{id}/toggle-status")] + public async Task> ToggleStatus(long id) + { + var client = await _context.OAuthApplications.FindAsync(id); + if (client == null) + { + return NotFound(); + } + + var oldStatus = client.Status; + client.Status = client.Status == "active" ? "inactive" : "active"; + client.UpdatedAt = DateTime.UtcNow; + + await _context.SaveChangesAsync(); + + await CreateAuditLog("oauth", "toggle_status", "OAuthClient", client.Id, client.DisplayName, oldStatus, client.Status); + + return Ok(new + { + clientId = client.ClientId, + oldStatus, + newStatus = client.Status, + message = $"客户端状态已从 {oldStatus} 更改为 {client.Status}" + }); + } + + [HttpPut("{id}")] + public async Task UpdateClient(long id, [FromBody] UpdateOAuthClientDto dto) + { + var client = await _context.OAuthApplications.FindAsync(id); + if (client == null) + { + return NotFound(); + } + + var application = await _applicationManager.FindByClientIdAsync(client.ClientId); + if (application == null) + { + return NotFound(); + } + + var descriptor = new OpenIddictApplicationDescriptor + { + ClientId = client.ClientId, + ClientSecret = client.ClientSecret, + DisplayName = dto.DisplayName ?? client.DisplayName + }; + + var redirectUris = dto.RedirectUris ?? client.RedirectUris; + foreach (var uri in redirectUris.Where(u => Uri.TryCreate(u, UriKind.Absolute, out _))) + { + descriptor.RedirectUris.Add(new Uri(uri)); + } + + var postLogoutUris = dto.PostLogoutRedirectUris ?? client.PostLogoutRedirectUris; + foreach (var uri in postLogoutUris.Where(u => Uri.TryCreate(u, UriKind.Absolute, out _))) + { + descriptor.PostLogoutRedirectUris.Add(new Uri(uri)); + } + + var grantTypes = dto.GrantTypes ?? client.GrantTypes; + foreach (var grantType in grantTypes) + { + descriptor.Permissions.Add(grantType); + } + + var scopes = dto.Scopes ?? client.Scopes; + foreach (var scope in scopes) + { + descriptor.Permissions.Add(scope); + } + + await _applicationManager.UpdateAsync(application, descriptor); + + client.DisplayName = dto.DisplayName ?? client.DisplayName; + client.RedirectUris = redirectUris; + client.PostLogoutRedirectUris = postLogoutUris; + client.Scopes = scopes; + client.GrantTypes = grantTypes; + client.ClientType = dto.ClientType ?? client.ClientType; + client.ConsentType = dto.ConsentType ?? client.ConsentType; + client.Status = dto.Status ?? client.Status; + client.Description = dto.Description ?? client.Description; + client.UpdatedAt = DateTime.UtcNow; + + await _context.SaveChangesAsync(); + + await CreateAuditLog("oauth", "update", "OAuthClient", client.Id, client.DisplayName, null, SerializeToJson(client)); return NoContent(); } @@ -191,16 +364,35 @@ public class OAuthClientsController : ControllerBase return NotFound(); } - var oldValue = SerializeToJson(client); + try + { + var application = await _applicationManager.FindByClientIdAsync(client.ClientId); + if (application != null) + { + await _applicationManager.DeleteAsync(application); + _logger.LogInformation("Deleted OpenIddict application {ClientId}", client.ClientId); + } + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Failed to delete OpenIddict application for client {ClientId}", client.ClientId); + } _context.OAuthApplications.Remove(client); await _context.SaveChangesAsync(); - await CreateAuditLog("oauth", "delete", "OAuthClient", client.Id, client.DisplayName, oldValue); + await CreateAuditLog("oauth", "delete", "OAuthClient", client.Id, client.DisplayName, SerializeToJson(client)); return NoContent(); } + private static string GenerateSecureSecret(int length = 32) + { + var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + var bytes = RandomNumberGenerator.GetBytes(length); + return new string(bytes.Select(b => chars[b % chars.Length]).ToArray()); + } + private async Task CreateAuditLog(string operation, string action, string targetType, long? targetId, string? targetName, string? oldValue = null, string? newValue = null) { var userName = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.Identity?.Name ?? "system"; @@ -225,7 +417,7 @@ public class OAuthClientsController : ControllerBase await _context.SaveChangesAsync(); } - private string SerializeToJson(object obj) + private static string SerializeToJson(object obj) { return System.Text.Json.JsonSerializer.Serialize(obj, new System.Text.Json.JsonSerializerOptions { @@ -237,27 +429,27 @@ public class OAuthClientsController : ControllerBase public class CreateOAuthClientDto { public string ClientId { get; set; } = string.Empty; - public string ClientSecret { get; set; } = string.Empty; + public string? ClientSecret { get; set; } public string DisplayName { get; set; } = string.Empty; - public string[] RedirectUris { get; set; } = Array.Empty(); - public string[] PostLogoutRedirectUris { get; set; } = Array.Empty(); - public string[] Scopes { get; set; } = Array.Empty(); - public string[] GrantTypes { get; set; } = Array.Empty(); - public string ClientType { get; set; } = "confidential"; - public string ConsentType { get; set; } = "implicit"; - public string Status { get; set; } = "active"; + public string[]? RedirectUris { get; set; } + public string[]? PostLogoutRedirectUris { get; set; } + public string[]? Scopes { get; set; } + public string[]? GrantTypes { get; set; } + public string? ClientType { get; set; } + public string? ConsentType { get; set; } + public string? Status { get; set; } public string? Description { get; set; } } public class UpdateOAuthClientDto { - public string DisplayName { get; set; } = string.Empty; - public string[] RedirectUris { get; set; } = Array.Empty(); - public string[] PostLogoutRedirectUris { get; set; } = Array.Empty(); - public string[] Scopes { get; set; } = Array.Empty(); - public string[] GrantTypes { get; set; } = Array.Empty(); - public string ClientType { get; set; } = "confidential"; - public string ConsentType { get; set; } = "implicit"; - public string Status { get; set; } = "active"; + public string? DisplayName { get; set; } + public string[]? RedirectUris { get; set; } + public string[]? PostLogoutRedirectUris { get; set; } + public string[]? Scopes { get; set; } + public string[]? GrantTypes { get; set; } + public string? ClientType { get; set; } + public string? ConsentType { get; set; } + public string? Status { get; set; } public string? Description { get; set; } } diff --git a/Controllers/RolesController.cs b/Controllers/RolesController.cs index 9beef92..2835160 100644 --- a/Controllers/RolesController.cs +++ b/Controllers/RolesController.cs @@ -123,7 +123,7 @@ public class RolesController : ControllerBase userName = u.UserName, email = u.Email, realName = u.RealName, - tenantId = u.TenantId, + tenantId = u.TenantInfo.Id, roles = await _userManager.GetRolesAsync(u), isActive = !u.LockoutEnabled || u.LockoutEnd == null || u.LockoutEnd < DateTimeOffset.UtcNow, createdAt = u.CreatedTime, diff --git a/Controllers/TenantsController.cs b/Controllers/TenantsController.cs index bb2ffc8..686443c 100644 --- a/Controllers/TenantsController.cs +++ b/Controllers/TenantsController.cs @@ -64,7 +64,7 @@ public class TenantsController : ControllerBase foreach (var tenant in tenants) { - var userCount = await _context.Users.CountAsync(u => u.TenantId == tenant.Id && !u.IsDeleted); + var userCount = await _context.Users.CountAsync(u => u.TenantInfo.Id == tenant.Id && !u.IsDeleted); result.Add(new { id = tenant.Id, @@ -127,7 +127,7 @@ public class TenantsController : ControllerBase } var users = await _context.Users - .Where(u => u.TenantId == tenant.Id && !u.IsDeleted) + .Where(u => u.TenantInfo.Id == tenant.Id && !u.IsDeleted) .ToListAsync(); var result = users.Select(async u => new @@ -136,7 +136,7 @@ public class TenantsController : ControllerBase userName = u.UserName, email = u.Email, realName = u.RealName, - tenantId = u.TenantId, + tenantId = u.TenantInfo.Id, roles = await _userManager.GetRolesAsync(u), isActive = !u.LockoutEnabled || u.LockoutEnd == null || u.LockoutEnd < DateTimeOffset.UtcNow, createdAt = u.CreatedTime, @@ -268,7 +268,7 @@ public class TenantsController : ControllerBase var oldValue = JsonSerializer.Serialize(tenant); - var users = await _context.Users.Where(u => u.TenantId == tenant.Id).ToListAsync(); + var users = await _context.Users.Where(u => u.TenantInfo.Id == tenant.Id).ToListAsync(); foreach (var user in users) { user.IsDeleted = true; diff --git a/Controllers/TokenController.cs b/Controllers/TokenController.cs index 1949792..03fc7f9 100644 --- a/Controllers/TokenController.cs +++ b/Controllers/TokenController.cs @@ -98,7 +98,7 @@ public class TokenController( new(Claims.Subject, await userManager.GetUserIdAsync(user)), new(Claims.Name, await userManager.GetUserNameAsync(user)), new(Claims.Email, await userManager.GetEmailAsync(user) ?? ""), - new("tenant_id", user.TenantId.ToString()) + new("tenant_id", user.TenantInfo.Id.ToString()) }; var roles = await userManager.GetRolesAsync(user); @@ -235,7 +235,7 @@ public class TokenController( new(Claims.Subject, await userManager.GetUserIdAsync(user)), new(Claims.Name, await userManager.GetUserNameAsync(user)), new(Claims.Email, await userManager.GetEmailAsync(user) ?? ""), - new("tenant_id", user.TenantId.ToString()) + new("tenant_id", user.TenantInfo.Id.ToString()) }; var roles = await userManager.GetRolesAsync(user); diff --git a/Controllers/UsersController.cs b/Controllers/UsersController.cs index 5c098c3..9781eed 100644 --- a/Controllers/UsersController.cs +++ b/Controllers/UsersController.cs @@ -52,7 +52,7 @@ public class UsersController : ControllerBase if (!string.IsNullOrEmpty(tenantId)) { - query = query.Where(u => u.TenantId.ToString() == tenantId); + query = query.Where(u => u.TenantInfo.Id.ToString() == tenantId); } var totalCount = await query.CountAsync(); @@ -69,7 +69,7 @@ public class UsersController : ControllerBase email = u.Email, realName = u.RealName, phone = u.Phone, - tenantId = u.TenantId, + tenantId = u.TenantInfo.Id, roles = (await _userManager.GetRolesAsync(u)).ToList(), emailConfirmed = u.EmailConfirmed, isActive = !u.LockoutEnabled || u.LockoutEnd == null || u.LockoutEnd < DateTimeOffset.UtcNow, @@ -103,7 +103,7 @@ public class UsersController : ControllerBase email = user.Email, realName = user.RealName, phone = user.Phone, - tenantId = user.TenantId, + tenantId = user.TenantInfo.Id, roles, emailConfirmed = user.EmailConfirmed, isActive = !user.LockoutEnabled || user.LockoutEnd == null || user.LockoutEnd < DateTimeOffset.UtcNow, @@ -114,13 +114,25 @@ public class UsersController : ControllerBase [HttpPost] public async Task> CreateUser(CreateUserDto dto) { + var tenantId = dto.TenantId ?? 0; + Tenant tenant = null; + + if (tenantId != 0) + { + tenant = await _context.Tenants.FindAsync(tenantId); + if (tenant == null) + { + return BadRequest("Invalid tenant ID"); + } + } + var user = new ApplicationUser { UserName = dto.UserName, Email = dto.Email, RealName = dto.RealName, Phone = dto.Phone, - TenantId = dto.TenantId ?? 0, + TenantInfo = new TenantInfo(tenantId, tenant?.TenantId ?? "default", tenant?.Name ?? "默认租户"), EmailConfirmed = dto.EmailConfirmed, CreatedTime = DateTime.UtcNow, }; diff --git a/Data/ApplicationDbContext.cs b/Data/ApplicationDbContext.cs index dd4e1d5..39ebe18 100644 --- a/Data/ApplicationDbContext.cs +++ b/Data/ApplicationDbContext.cs @@ -24,7 +24,6 @@ public class ApplicationDbContext : IdentityDbContext e.RealName).HasMaxLength(100); entity.Property(e => e.Phone).HasMaxLength(20); - entity.HasIndex(e => e.TenantId); entity.HasIndex(e => e.Phone).IsUnique(); }); diff --git a/Data/SeedData.cs b/Data/SeedData.cs index 017c766..e5184c4 100644 --- a/Data/SeedData.cs +++ b/Data/SeedData.cs @@ -83,7 +83,7 @@ public static class SeedData Email = "admin@fengling.local", RealName = "系统管理员", Phone = "13800138000", - TenantId = defaultTenant.Id, + TenantInfo = new TenantInfo(defaultTenant.Id, defaultTenant.TenantId, defaultTenant.Name), EmailConfirmed = true, IsDeleted = false, CreatedTime = DateTime.UtcNow @@ -105,7 +105,7 @@ public static class SeedData Email = "test@fengling.local", RealName = "测试用户", Phone = "13900139000", - TenantId = defaultTenant.Id, + TenantInfo = new TenantInfo(defaultTenant.Id, defaultTenant.TenantId, defaultTenant.Name), EmailConfirmed = true, IsDeleted = false, CreatedTime = DateTime.UtcNow diff --git a/Models/ApplicationUser.cs b/Models/ApplicationUser.cs index d1b4fa5..9bb5297 100644 --- a/Models/ApplicationUser.cs +++ b/Models/ApplicationUser.cs @@ -6,7 +6,7 @@ public class ApplicationUser : IdentityUser { public string? RealName { get; set; } public string? Phone { get; set; } - public long TenantId { get; set; } + public TenantInfo TenantInfo { get; set; } = null!; public DateTime CreatedTime { get; set; } = DateTime.UtcNow; public DateTime? UpdatedTime { get; set; } public bool IsDeleted { get; set; } diff --git a/Models/Tenant.cs b/Models/Tenant.cs index d25c7c2..e836cf6 100644 --- a/Models/Tenant.cs +++ b/Models/Tenant.cs @@ -4,16 +4,32 @@ namespace Fengling.AuthService.Models; public class Tenant { + private long _id; + private string _tenantId; + private string _name; + [Key] - public long Id { get; set; } + public long Id + { + get => _id; + set => _id = value; + } [MaxLength(50)] [Required] - public string TenantId { get; set; } = string.Empty; + public string TenantId + { + get => _tenantId; + set => _tenantId = value; + } [MaxLength(100)] [Required] - public string Name { get; set; } = string.Empty; + public string Name + { + get => _name; + set => _name = value; + } [MaxLength(50)] [Required] @@ -43,5 +59,5 @@ public class Tenant public bool IsDeleted { get; set; } - public ICollection Users { get; set; } = new List(); + public TenantInfo Info => new(Id, TenantId, Name); } diff --git a/Models/TenantInfo.cs b/Models/TenantInfo.cs new file mode 100644 index 0000000..0f4fa48 --- /dev/null +++ b/Models/TenantInfo.cs @@ -0,0 +1,3 @@ +namespace Fengling.AuthService.Models; + +public record TenantInfo(long Id, string TenantId, string Name); diff --git a/Views/Account/Login.cshtml b/Views/Account/Login.cshtml index 156b39f..97e3ef4 100644 --- a/Views/Account/Login.cshtml +++ b/Views/Account/Login.cshtml @@ -31,6 +31,7 @@ }
+ @Html.AntiForgeryToken()
diff --git a/Views/Account/Register.cshtml b/Views/Account/Register.cshtml index cd58d86..ff97408 100644 --- a/Views/Account/Register.cshtml +++ b/Views/Account/Register.cshtml @@ -32,6 +32,7 @@ } + @Html.AntiForgeryToken()
diff --git a/Views/Shared/_Layout.cshtml b/Views/Shared/_Layout.cshtml index 533acb9..6e46ebf 100644 --- a/Views/Shared/_Layout.cshtml +++ b/Views/Shared/_Layout.cshtml @@ -56,24 +56,26 @@ - - + +
} else { - - 登录 - - 注册 - + + 登录 + + 注册 + }
diff --git a/wwwroot/login.html b/wwwroot/login.html deleted file mode 100644 index 2bf3304..0000000 --- a/wwwroot/login.html +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - 登录 - 风铃认证服务 - - - -
-

风铃认证服务

- -
- -
- - -
-
- - -
-
- - -
- -
-
- - - -