Токен не может храниться в. NET Core - PullRequest
2 голосов
/ 31 марта 2020

У меня есть проект, использующий. NET базовая версия 3.1, и я использую токен для входа в систему. При тестировании с помощью Postman все работает отлично, он создал токен, и я могу использовать его для доступа к домашней странице.

Проблема в том, что когда я начал тестирование на стороне клиента, он не работает. После отладки я обнаружил, что токен сгенерирован, но я не могу получить доступ к HomeController из-за атрибута [Authorize].

Это мой код для генерации токена:

public async Task<HttpResponse<LoginResult>> GetTokenAsync(LoginRequest loginInfo)
{
    var audience = await _audiences.FindAsync(a => a.Id == loginInfo.ClientId);
    string message = string.Empty;

    if (audience != null)
    {
        bool audienceIsValid = _jwtProvider.ValidateAudience(audience.Issuer
                    , audience.SecretKey
                    , ref message);

        if (audienceIsValid)
            return await GenerateToken(loginInfo);
        else
            message = ErrorMessages.Login_AudienceInvalid;
    }
    else
        message = string.Format(ErrorMessages.Login_Not_Permitted, "Your client Id");
    return HttpResponse<LoginResult>.Error(message, HttpStatusCode.BadRequest);
}

Я полагаю, что токен не может быть правильно сохранен.

Что мне не хватает?

ОБНОВЛЕНИЕ Это мой код при входе в систему

[HttpPost]
[Route("login")]
[AllowAnonymous]
public async Task<ActionResult> Login([FromForm]LoginRequest model)
{
      model.ClientId = 1;
      var response = await _services.GetTokenAsync(model);
      if (response.StatusCode == 200)
      {
           return RedirectToAction("Index", "Home");
      }
      return RedirectToAction("Login");
}

И вот что Я пытаюсь получить доступ к

[HttpGet]
[Route("index")]
[Authorize]
public IActionResult Index()
{
     return View();
}

1 Ответ

0 голосов
/ 31 марта 2020

Необходимо создать настраиваемую политику, указав ее в атрибуте Authorize, который настроен на использование настраиваемого обработчика требований.

Сначала вы задаете требование настраиваемой политики через класс, который наследует IAuthorizationRequirement

public class TokenRequirement : IAuthorizationRequirement
{
}

Здесь вы можете принять параметры, если они вам нужны. Но обычно вы передаете токен в заголовке запроса, к которому обработчик требований вашей пользовательской политики будет иметь доступ без необходимости явных параметров.

Обработчик требований вашего требования, который будет использоваться вашей пользовательской политикой, будет выглядеть примерно так this

public class TokenHandler : AuthorizationHandler<TokenRequirement>
{
    //Some kind of token validator logic injected into your handler via DI
    private readonly TokenValidator _tokenValidator;

    //The http context of this request session also injected via DI
    private readonly IHttpContextAccessor _httpCtx;

    //The name of the header your token can be found under on a Http Request
    private const string tokenHeaderKey = "authToken";

    //Constructor using DI to get a instance of a TokenValidator class you would
    //have written yourself, and the httpContext
    public TokenHandler(TokenValidator tokenValidator, IHttpContextAccessor httpCtx)
    {
        _tokenValidator = tokenValidator;
        _httpCtx = httpCtx;
    }

    //Overriden implementation of base class AuthorizationHandler's HandleRequirementAsync method 
    //This is where you check your token.
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context
        ,TokenRequirement requirement)
    {
        if (context.Resource is Endpoint endpoint)
        {
            HttpRequest httpReqCtx = _httpCtx.HttpContext.Request;
            string token =
                httpReqCtx.Headers.TryGetValue(tokenHeaderKey, out StringValues tokenVal)
                    ? tokenVal.FirstOrDefault()
                    : null;

            if (string.IsNullOrWhitespace(token))
            {
                context.Fail();
            }
            else
            {
                bool tokenIsValid = await _tokenValidator.ValidToken(token);
                if(tokenIsValid)
                    context.Succeed(requirement);
                else
                    context.Fail();
            }
        }
        return Task.CompletedTask;
    }
}

Вы бы зарегистрировали свой обработчик пользовательских требований для имени пользовательской политики в Startup.cs, например, так:

//This is a framework extension method under Microsoft.Extensions.DependencyInjection
services.AddHttpContextAccessor();

//Your custom handler
services.AddSingleton<IAuthorizationHandler, TokenHandler>();

//Your custom policy
services.AddAuthorization(options =>
{
    options.AddPolicy(
        //Your custom policy's name, can be whatever you want
        "myCustomTokenCheckerPolicy",
        //The requirement your policy is going to check
        //Which will be handled by the req handler added above
        policy => policy.Requirements.Add(new TokenRequirement())
    );
});

Значение атрибута будет выглядеть следующим образом

[HttpGet]
[Route("index")]
[Authorize(Policy = "myCustomTokenCheckerPolicy")]
public IActionResult Index()
{
    return View();
}
...