sso优化

This commit is contained in:
2026-08-03 20:30:32 +08:00 Unverified
parent 5ec62a03ca
commit 6735a6d3fc
14 changed files with 540 additions and 30 deletions
+67 -2
View File
@@ -1,13 +1,17 @@
using System.Text.Json;
using System.Security.Claims;
using Jiaowu.Api.Controllers;
using Jiaowu.Api.Domain.Identity;
using Jiaowu.Api.Infrastructure.Auth;
using Jiaowu.Api.Infrastructure.Persistence;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
namespace Jiaowu.Api.Tests;
@@ -54,6 +58,52 @@ public sealed class SsoControllerTests
Assert.Equal(1, user?.AccessFailedCount);
}
[Fact]
public async Task Account_ReportsCurrentKeycloakBindingAndConfiguredCallback()
{
await using var fixture = await BindingFixture.CreateAsync();
Assert.True((await fixture.UserManager.AddLoginAsync(
fixture.User,
new UserLoginInfo(
SsoAuthSchemes.LoginProvider,
"keycloak-subject",
"学校统一身份认证"))).Succeeded);
fixture.SignInController();
var result = await fixture.Controller.Account();
var response = Assert.IsType<SsoAccountResponse>(result.Value);
Assert.True(response.Enabled);
Assert.True(response.IsBound);
Assert.Equal(
"https://jiaowu.example.edu.cn/signin-keycloak",
response.CallbackUrl);
}
[Fact]
public async Task Unbind_WithCurrentPassword_RemovesOnlyKeycloakLogin()
{
await using var fixture = await BindingFixture.CreateAsync();
Assert.True((await fixture.UserManager.AddLoginAsync(
fixture.User,
new UserLoginInfo(
SsoAuthSchemes.LoginProvider,
"keycloak-subject",
"学校统一身份认证"))).Succeeded);
fixture.SignInController();
var result = await fixture.Controller.Unbind(
new SsoUnbindRequest("LocalUser@123"));
Assert.IsType<NoContentResult>(result);
Assert.Null(await fixture.UserManager.FindByLoginAsync(
SsoAuthSchemes.LoginProvider,
"keycloak-subject"));
Assert.True(await fixture.UserManager.CheckPasswordAsync(
fixture.User,
"LocalUser@123"));
}
[Theory]
[InlineData(null, "/dashboard")]
[InlineData("", "/dashboard")]
@@ -93,6 +143,19 @@ public sealed class SsoControllerTests
public IDistributedCache Cache { get; }
public SsoController Controller { get; }
public void SignInController()
{
Controller.ControllerContext = new ControllerContext
{
HttpContext = new DefaultHttpContext
{
User = new ClaimsPrincipal(new ClaimsIdentity(
[new Claim(ClaimTypes.NameIdentifier, User.Id.ToString())],
"test"))
}
};
}
public static async Task<BindingFixture> CreateAsync()
{
var connection = new SqliteConnection("Data Source=:memory:");
@@ -127,8 +190,10 @@ public sealed class SsoControllerTests
Options.Create(new SsoOptions
{
Enabled = true,
DisplayName = "学校统一身份认证"
}));
DisplayName = "学校统一身份认证",
CallbackUrl = "https://jiaowu.example.edu.cn/signin-keycloak"
}),
NullLogger<SsoController>.Instance);
return new BindingFixture(
connection,
provider,