Приложение ASP.Net Core 2.1 / WebAPI: «HTTP 404 не найден», вызывая REST-URL с помощью [Авторизовать] - PullRequest
0 голосов
/ 20 ноября 2018

Я работаю над учебным пособием "Здравствуй, мир!" На Asp.Net Core.Я использую WebApi (не MVC).

Вот контроллер REST API, который я пытаюсь вызвать:

...
[Authorize]
[Route("api/[controller]")]
[ApiController]

public class ManageCarController : ControllerBase
{
    private IMapper mapper;
    private ApplicationDbContext dbContext;

    public ManageCarController(IMapper mapper, ApplicationDbContext dbContext)
    {
        this.mapper = mapper;
        this.dbContext = dbContext;
    }

    // GET api/values
    [HttpGet]
    public IEnumerable<CarViewModel> Get()
    {
        IEnumerable<CarViewModel> list =
            this.mapper.Map<IEnumerable<CarViewModel>>(this.dbContext.cars.AsEnumerable());
    return list;
}
...

Вот мой контроллер для входа в систему:

...
[Authorize]
[Route("[controller]/[action]")]
public class AccountController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;
    private readonly ILogger _logger;

    public AccountController(
        UserManager<ApplicationUser> userManager,
        SignInManager<ApplicationUser> signInManager,
        ILogger<AccountController> logger)
    {
        _userManager = userManager;
        _signInManager = signInManager;
        _logger = logger;
    }

    [TempData]
    public string ErrorMessage { get; set; }
    [HttpPost]
    [AllowAnonymous]
    public async Task<IActionResult> Login([FromBody]LoginViewModel model)
    {
        if (ModelState.IsValid)
        {
            // This doesn't count login failures towards account lockout
            // To enable password failures to trigger account lockout, set lockoutOnFailure: true
            var result = await _signInManager.PasswordSignInAsync
                (model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
            if (result.Succeeded)
            {
                var msg = "User logged in.";
                return Ok(msg);
            }
        }
        // If we got this far, something failed, redisplay form
        return BadRequest("Fail to login with this account");
    }

Я могу войти (http://localhost:5000/Login) ОК, ответ «Пользователь вошел в систему».

Когда я перехожу на http://localhost:5000/api/ManageCar, он перенаправляет сюда и дает мне HTTP 404:https://localhost:44342/Account/Login?ReturnUrl=%2Fapi%2FManageCar, и я никогда не нажимаю на контроллер.

Если я закомментирую [Authorize], тогда http://localhost:5000/api/ManageCar работает нормально.

В: Чего мне не хватает?

В: Что важнее, как лучше решить проблему?

В: Какую (если таковую) дополнительную информацию я должен предоставить?

Заранее спасибо!


ОБНОВЛЕНИЕ:

  1. Перед вызовом http://localhost:5000/api/ManageCar я сначала вхожу (успешно).

  2. Вот что ясм. в Edge> Инструменты разработчика> Сеть:

    Name    Protocol    Method  Result  Content type    Received    Time    Initiator
    https://localhost:44342/Account/Login   HTTP/2  POST    200 application/json        9.31 s  XMLHttpRequest
      <= Login: OK
    https://localhost:44342/Account/Login   HTTPS   GET 200     (from cache)    0 s 
      <= ManageCars (GET@1): OK
    https://localhost:44342/api/ManageCar   HTTP/2  GET 302     0 B 97.43 ms    XMLHttpRequest
      <= ManageCars (GET@2 - 302 redirect to REST API): OK
    https://localhost:44342/Account/Login?ReturnUrl=%2Fapi%2FManageCar  HTTP/2  GET 404     0 B 16.77 ms    XMLHttpRequest
      <= ManageCars (GET@3 - 404: not found): FAILS
         - Console:
    HTTP 404: NOT FOUND - The server has not found anything matching the requested URI (Uniform Resource Identifier).
    (XHR)GET - https://localhost:44342/Account/Login?ReturnUrl=%2Fapi%2FManageCar
    

УТОЧНЕНИЕ ОТВЕТА Тана Нгуайна:

  1. У меня есть REST API, написанный наC # с использованием Asp.Net Core 2.1 + веб-API.
  2. В API есть метод "GET", /api/ManageCar.Если я звоню без [Авторизовать], это работает.
  3. Я "защищаю" API с помощью Asp.Net Core Identity .URL-адрес «/ Аккаунт / Логин».Необходимо использовать POST (для передачи имени пользователя и пароля).Это тоже работает.
  4. Если я аннотирую «ManageCar» с помощью [Authorize], а затем авторизируюсь (успешно), то THEN GET /api/ManageCar ... он НЕ перейдет непосредственно к моему контроллеру для"/api/ManageCar".
  5. Вместо этого он переходит в" / Account / Login "(я уже вошел в систему, результат HTTP 200), затем перенаправляет на" https://localhost:44342/Account/Login?ReturnUrl=%2Fapi%2FManageCar"/
  6. I должен быть в состоянии сделать POST для моего логина и GET для моего (теперь аутентифицированного) запроса - он должен"просто работать".
  7. К сожалению, я не знаю, что делает Asp.Net "за кулисами" ... и я не знаю, что является причиной проблемы или как ее устранить.

ОБНОВЛЕНИЕ

  1. Я все еще не решил проблему - я все еще получаю HTTP 404 с [Authorize], и он работает без [Authorize]

  2. И мой AccountController, и ManageCarController имеют одинаковый путь: [Route("api/[controller]/[action])]' and [Route ("api / [controller])]`, соответственно.Я все еще могу войти в систему успешно, я все еще получаю HTTP 404. Когда я пытаюсь прочитать список "Cars".

  3. Я включил регистрацию "Trace" в моем appsettings.json.Вот сводная информация о выходе неудачного вызова API:

    Console log:
    - Request starting HTTP/1.1 GET http://localhost:63264/api/ManageCar  
      Request finished in 81.994ms 302
    - Request starting HTTP/1.1 GET http://localhost:63264/Account/Login?ReturnUrl=%2Fapi%2FManageCar 
      AuthenticationScheme: Identity.Application was successfully authenticated.
      The request path /Account/Login does not match a supported file type
      The request path  does not match the path filter
      Request finished in 31.9471ms 404
      SUMMARY:
      a) request to "ManageCar" redirects to AccountController => OK
      b) AccountController gets the request => OK
      c) Q: Does AccountController authenticate the request? 
         <= it *seems* to ("successfully authenticated"...)
      d) Q: What do "match a supported file type" or "match the path filter" mean?  
            What can I do about them?
    

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

Я думаю, что это проблема маршрутизации, вы можете проверить свои маршруты.Вы заметили, что два контроллера имеют два маршрута каждый [Маршрут ("[контроллер] / [действие]")] и [Маршрут ("api / [контроллер]")].

Если ваши маршрутыХорошо, вы должны проверить свой механизм аутентификации.Как проверить, аутентифицирован ли пользователь и как перенаправить, потому что вам не нужно перенаправлять на ваш метод входа в каждый метод Api, если вы уже прошли аутентификацию.

Спасибо.

0 голосов
/ 20 ноября 2018

Если я правильно понял, вы имели в виду две проблемы:

  1. Вы пытаетесь получить доступ к /api/ManageCar без входа в систему.Атрибут [Authorize] означает: этот контроллер / действие требует входа в систему перед назначением.

Вот почему он перенаправлен на путь: /Account/Login?ReturnUrl=%2Fapi%2FManageCar

Вы можете проверить путь, там2 части:

  • Первая часть: /Account/Login.Это URL страницы входа в систему.

  • Вторая часть: ?ReturnUrl=%2Fapi%2FManageCar.Мы можем понять это как: ?ReturnUrl=/api/ManageCar, потому что %2F означает /.Эта строка запроса параметра означает: после успешного входа в систему запрос будет перенаправлен на /api/ManaCar.

  • Вторая проблема может быть следующей: в методе Get вы устанавливаете его как метод GET с помощью [HttpGet].Это означает, что этот метод может быть назначен только через метод GET.Итак, если вы пытаетесь сделать запрос POST, он не будет работать.

[HttpGet]
public IEnumerable<CarViewModel> Get()
{
    IEnumerable<CarViewModel> list =
        this.mapper.Map<IEnumerable<CarViewModel>>(this.dbContext.cars.AsEnumerable());
    return list;
}

Если вы используете jquery, послевход выполнен успешно, вы можете попытаться сделать запрос GET следующим образом:

$.get('/api/ManageCar').done(function (data) {
    console.log(data);
});

Или изменить атрибут [HttpGet] на атрибут [HttpPost]:

$.post('/api/ManageCar').done(function (data) {
    console.log(data);
});
...