代码之家  ›  专栏  ›  技术社区  ›  FoggyDay

ASP.NET Core 2.1/WebAPI应用程序:“未找到HTTP 404”使用[授权]调用REST URL

  •  2
  • FoggyDay  · 技术社区  · 6 年前

    我正在学习有关ASP.NET核心的“Hello World”教程。我使用的是WebAPI(不是MVC)。

    下面是我尝试调用的RESTAPI的控制器:

    ...
    [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
      

    T_、N__N答复澄清:

    1. 我有一个RESTAPI,用C语言编写,使用ASP.NET核心2.1+Web API。
    2. API有一个“get”方法, /api/ManageCar . 如果我没有[授权]打电话,它会起作用。
    3. 我正在用“保护”API Asp.Net Core Identity .URL是'/account/login'。它需要使用post(传递用户名和密码)。这也行。
    4. 如果我用[授权]注释“managecar”,然后登录(成功),那么 然后 得到 /API/管理器 …它不会直接转到我的控制器中的“/api/managecar”。
    5. 相反,它会转到“/account/login”(我已经登录,结果是http 200),然后重定向到) https://localhost:44342/Account/Login?ReturnUrl=%2Fapi%2FManageCar
    6. 应该 能够为我的登录做一个帖子,为我的(现在已经认证的)查询做一个GET-IT 应该 “只是工作”。
    7. 不幸的是,我不知道ASP.NET在“幕后”做什么……我不知道是什么导致了这个问题,也不知道如何解决它。

    更新

    1. 我仍然没有解决这个问题-我仍然得到HTTP 404 [授权] 而且它不需要 [授权]

    2. 我的AccountController和ManageCardController的路径相同: [Route("api/[controller]/[action])]' and [路由(“api/[控制器])`。我仍然可以成功登录,当我试图阅读“汽车”列表时,我仍然可以得到HTTP404。

    3. 我启用了“跟踪”登录 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 回复  |  直到 6 年前
        1
  •  1
  •   MNF    6 年前

    我认为这是一个路线问题,你能核实一下你的路线吗? 你注意到两个控制器每一个有两条线路吗 [路由(“[控制器]/[操作]”)]和[路由(“API/[控制器]”)]。

    如果路由正常,则应检查身份验证机制。 如何检查用户是否已通过身份验证,以及如何重定向,因为如果已经通过身份验证,则不需要在每个API方法中重定向到登录方法。

    谢谢。

        2
  •  1
  •   Tân    6 年前

    如果我理解你的意思,问题可能来自两个方面:

    1. 您正在尝试访问 /api/ManageCar 无需登录。属性 [Authorize] 意味着:此控制器/操作在分配给之前需要登录。

    这就是它重定向到路径的原因: /Account/Login?ReturnUrl=%2Fapi%2FManageCar

    您可以检查路径,共有两部分:

    • 第一部分是: /Account/Login . 这是登录页面的URL。

    • 第二部分是: ?ReturnUrl=%2Fapi%2FManageCar . 我们可以 理解 比如: ?ReturnUrl=/api/ManageCar 因为 %2F 代表 / . 此参数查询字符串表示:登录成功后,请求将被重定向到 /api/ManaCar .

      1. 第二个问题可能是:在 Get 方法,通过使用将其设置为get方法 [HttpGet] . 这意味着只能通过使用get方法将此方法分配给。所以,如果你试图提出一个发帖请求,它将不起作用。

    [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);
    });