162 lines
5.1 KiB
C#
162 lines
5.1 KiB
C#
using System.Security.Claims;
|
|
using Yh.Platform.Abstractions;
|
|
using Yh.Platform.Auth;
|
|
using Xunit;
|
|
|
|
namespace Yh.Platform.Auth.Tests;
|
|
|
|
/// <summary>CAS serviceValidate 响应 XML 用户提取对拍(对齐 Java CasServiceTicketValidator)。</summary>
|
|
public class CasServiceTicketValidatorTests
|
|
{
|
|
[Fact]
|
|
public void 成功响应_提取cas_user()
|
|
{
|
|
var xml = """
|
|
<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
|
|
<cas:authenticationSuccess>
|
|
<cas:user>zhangsan</cas:user>
|
|
</cas:authenticationSuccess>
|
|
</cas:serviceResponse>
|
|
""";
|
|
Assert.Equal("zhangsan", CasServiceTicketValidator.ExtractUser(xml));
|
|
}
|
|
|
|
[Fact]
|
|
public void 带属性容错_提取cas_user()
|
|
{
|
|
var xml = "<cas:serviceResponse><cas:authenticationSuccess><cas:user index=\"0\">lisi</cas:user></cas:authenticationSuccess></cas:serviceResponse>";
|
|
Assert.Equal("lisi", CasServiceTicketValidator.ExtractUser(xml));
|
|
}
|
|
|
|
[Fact]
|
|
public void 失败响应_返回null()
|
|
{
|
|
var xml = """
|
|
<cas:serviceResponse xmlns:cas="http://www.yale.edu/tp/cas">
|
|
<cas:authenticationFailure code="INVALID_TICKET">
|
|
Ticket ST-1856339 not recognized
|
|
</cas:authenticationFailure>
|
|
</cas:serviceResponse>
|
|
""";
|
|
Assert.Null(CasServiceTicketValidator.ExtractUser(xml));
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("")]
|
|
[InlineData(null)]
|
|
[InlineData("<cas:serviceResponse></cas:serviceResponse>")]
|
|
public void 无用户节点或空输入_返回null(string? xml)
|
|
{
|
|
Assert.Null(CasServiceTicketValidator.ExtractUser(xml));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task 未配置CAS地址_抛AuthException()
|
|
{
|
|
var validator = new CasServiceTicketValidator("");
|
|
var ex = await Assert.ThrowsAsync<AuthException>(() => validator.ValidateAsync("ST-1", "http://app/cb"));
|
|
Assert.Contains("cas-server-url-prefix", ex.Message);
|
|
}
|
|
}
|
|
|
|
public class BoaUserContextTests
|
|
{
|
|
[Fact]
|
|
public async Task 异步流内可读取_请求结束清理()
|
|
{
|
|
Assert.Null(BoaUserContext.Get());
|
|
Assert.Null(UserContextHolder.Get());
|
|
|
|
BoaUser? seenInChild = null;
|
|
var user = new BoaUser(1001, "zhangsan", "张三");
|
|
BoaUserContext.Set(user);
|
|
UserContextHolder.Set(new LoginUser("1001") { LoginName = "zhangsan", DisplayName = "张三" });
|
|
|
|
await Task.Run(() =>
|
|
{
|
|
// AsyncLocal 值随执行上下文流入子任务
|
|
seenInChild = BoaUserContext.Get();
|
|
});
|
|
|
|
Assert.Same(user, seenInChild);
|
|
Assert.Equal("zhangsan", UserContextHolder.Get()?.LoginName);
|
|
|
|
BoaUserContext.Clear();
|
|
UserContextHolder.Clear();
|
|
Assert.Null(BoaUserContext.Get());
|
|
Assert.Null(UserContextHolder.Get());
|
|
}
|
|
|
|
[Fact]
|
|
public void LoginUser_属性封装()
|
|
{
|
|
var login = new LoginUser("1001")
|
|
{
|
|
LoginName = "zhangsan",
|
|
DisplayName = "张三",
|
|
AppKey = "app-001",
|
|
};
|
|
Assert.Equal("1001", login.UserId);
|
|
Assert.Equal("zhangsan", login.LoginName);
|
|
Assert.Equal("张三", login.DisplayName);
|
|
Assert.Equal("app-001", login.AppKey);
|
|
}
|
|
}
|
|
|
|
public class UserContextMiddlewareTests
|
|
{
|
|
private sealed class StubProvider : IUserDetailsProvider
|
|
{
|
|
public BoaUser? User { get; set; } = new(1001, "zhangsan", "张三");
|
|
|
|
public Task<BoaUser?> GetByLoginNameAsync(string loginName, CancellationToken ct = default)
|
|
=> Task.FromResult(User);
|
|
}
|
|
|
|
private static HttpContext HttpContextWithLogin(string loginName)
|
|
{
|
|
var identity = new ClaimsIdentity("CAS");
|
|
identity.AddClaim(new Claim("loginName", loginName));
|
|
var context = new DefaultHttpContext();
|
|
context.User = new ClaimsPrincipal(identity);
|
|
return context;
|
|
}
|
|
|
|
[Fact]
|
|
public async Task 认证请求_中间件写入上下文_业务管道内可读()
|
|
{
|
|
var provider = new StubProvider();
|
|
BoaUser? seen = null;
|
|
LoginUser? seenLogin = null;
|
|
var middleware = new UserContextMiddleware(_ =>
|
|
{
|
|
seen = BoaUserContext.Get();
|
|
seenLogin = UserContextHolder.Get();
|
|
return Task.CompletedTask;
|
|
});
|
|
|
|
await middleware.InvokeAsync(HttpContextWithLogin("zhangsan"), provider);
|
|
|
|
Assert.NotNull(seen);
|
|
Assert.Equal(1001, seen!.Id);
|
|
Assert.Equal("zhangsan", seenLogin?.LoginName);
|
|
Assert.Equal("张三", seenLogin?.DisplayName);
|
|
// 请求结束后必须清空,防串扰
|
|
Assert.Null(BoaUserContext.Get());
|
|
Assert.Null(UserContextHolder.Get());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task 未认证请求_不写上下文直接放行()
|
|
{
|
|
var provider = new StubProvider();
|
|
var middleware = new UserContextMiddleware(_ => Task.CompletedTask);
|
|
|
|
var context = new DefaultHttpContext(); // 匿名
|
|
await middleware.InvokeAsync(context, provider);
|
|
|
|
Assert.Null(BoaUserContext.Get());
|
|
Assert.Null(UserContextHolder.Get());
|
|
}
|
|
}
|