Можете ли вы предоставить источник для "создания ClaimsPrincipal для тестирования гораздо проще и правильнее, чем то, что вы пытаетесь сделать"?
Источник - я.Что касается того, почему я это сказал, то оно основано на понимании того, как написано ядро ASP NET Core , как я продемонстрирую ниже.
Чтобы ответить на ваш вопрос, у Controller есть свойство User для доступа к утверждениям, нет необходимости писать Model Binder для доступа к утверждениям, когда свойство User уже существует, если, конечно, вы не можете получить доступ к утверждениям этого пользователясобственность из-за вашей логики претензий быть другим.Но вы не делали таких упоминаний.
"Я хочу иметь возможность предоставить заявку от текущего пользователя непосредственно в параметрах контроллера. Чтобы я мог писать модульные тесты, не касаясьПринцип магии Claim. "
Я интерпретировал это как
" Я хочу написать модульные тесты для моего контроллера, который имеет логику с использованием принципала утверждений, но я не знаю, какпредоставить поддельный принципал утверждений, поэтому я собираюсь избежать этого и передать вместо него параметр метода "
ClaimsPrincipal может быть не магическим, как показано ниже.
Controller
имеет свойство User
, но это только Get. Магия HttpContext
имеет свойство User
, которое является Get и Set ( Nice ), но Controller.HttpContext
is Get only ( Not So Nice) Controller
имеет свойство ControllerContext
, которое является Get и Set, ControllerContext
имеет свойство HttpContext
, которое является Get и Set. Джекпот!
Это исходный код из ControllerBase
, из которого Controller
и ApiController
происходят,
public abstract class ControllerBase
{
/* simplified below */
public ControllerContext ControllerContext
{
get => _controllerContext;
set => _controllerContext = value;
}
/* ... */
public HttpContext HttpContext => ControllerContext.HttpContext;
/* ... */
public ClaimsPrincipal User => HttpContext?.User;
}
Как вы видите здесь, пользователь, к которому вы обращаетесь, - это удобный инструмент, который в конечном итоге обращается к ControllerContext.HttpContext.User
.Зная эту информацию, вы можете выполнить модульное тестирование контроллера, который использует ClaimsPrincipal, следующим образом.
// Create a principal according to your requirements, following is exemplary
var principal = new ClaimsPrincipal(new ClaimsIdentity(new []
{
// you might have to use ClaimTypes.Name even for JWTs issued as sub.
new Claim(JwtRegisteredClaimNames.Sub, "1234"),
new Claim(JwtRegisteredClaimNames.Iss, "www.example.com"),
}, "Bearer"));
var httpContext = new DefaultHttpContext();
httpContext.User = principal;
// Fake anything you want
httpContext.Request.Headers = /* ... */
var controller = new ControllerUnderTest(...);
controller.ControllerContext = new ControllerContext();
controller.ControllerContext.HttpContext = httpContext;
// Test the action, no need to pass claims as parameters because the User property is set
var result = controller.ActionThatUsesUserClaims(...);
Assert.Something(result, expected);
Именно так работает ASP NET Core при каждом получении реального веб-запроса.Это буквально делает вышеперечисленное, чтобы сделать контроллер работоспособным и готовым к использованию.
Все вышеперечисленное является частью public ASP NET Core API и не подвержено критическим изменениям безосновная версия Bumb, поэтому они безопасны в использовании.Фактически, это одна из вещей, которая отличает ASP Net Core от старого ASP NET MVC, который был кошмаром для тестирования, поскольку он не раскрывал ничего из вышеперечисленного публично.
Сказав все это, дляпочему-то я упустил из виду, что если вам действительно нужно написать связыватель модели для предоставления утверждений, введите HTTPContextAccessor .Но для этого необходимо проверить тип параметров метода и выполнение ветвления.Одна ветвь будет связывать свойства из провайдера значений, а другая - из HttpContext.Но зачем беспокоиться, если вы можете сделать выше с рефакторингом 0?