#asp.net #asp.net-mvc #api
#asp.net #asp.net-mvc #API
Вопрос:
В ASP.NET В основном проекте Rest API я настроил пользовательскую аутентификацию и могу комментировать действия контроллера с помощью [Authorize]
атрибута, который перенаправляет неавторизованные запросы обратно на мой AuthController:
[Route("api/[controller]")]
[ApiController]
public class ResponseController : ControllerBase
{
[Authorize]
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return JsonConvert.SerializeObject(Repository.GetResponse(id), Formatting.Indented);
}
}
[Route("api/[controller]")]
[ApiController]
public class MetaController : ControllerBase
{
[Authorize]
[HttpGet("{id}")]
public ActionResult<string> Get(int id)
{
return JsonConvert.SerializeObject(Repository.GetMeta(id), Formatting.Indented);
}
}
[Route("api/[controller]")]
[ApiController]
public class AuthController : Controller
{
UserManager _userManager;
public AuthController(UserManager userManager)
{
_userManager = userManager;
}
[HttpGet]
[HttpPost]
public ActionResult<string> LogIn()
{
try
{
//authenticate
var username = Request.Headers["username"];
var password = Request.Headers["pass"];
if (String.IsNullOrEmpty(username) || String.IsNullOrEmpty(password))
throw new Exception("Authentication Exception: Missing Username or Password");
Task.Run(async () => {
await _userManager.SignInAsync(this.HttpContext, username, password);
}).GetAwaiter().GetResult();
return RedirectToAction("Search", "Home", null);
//^^^ How to send back to intended action?^^^
}
catch (Exception ex)
{
return AuthError();
}
}
}
Это работает, за исключением того, как мне использовать RedirectToAction
метод для возврата обратно к предполагаемому контроллеру ( MetaController
или ResponseController
, в данном случае)? (тот, у которого отмечен метод [Authorize]
, который для начала ввел нас в этот контроллер аутентификации)
Ответ №1:
Вам нужно использовать параметр returnUrl, например, так:
[HttpGet]
[HttpPost]
public async Task<IActionResult> LogIn(string returnUrl = null)
{
try
{
//authenticate
var username = Request.Headers["username"];
var password = Request.Headers["pass"];
if (String.IsNullOrEmpty(username) || String.IsNullOrEmpty(password))
throw new Exception("Authentication Exception: Missing Username or Password");
await _userManager.SignInAsync(this.HttpContext, username, password);
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
return RedirectToAction("Search", "Home", null);
}
catch (Exception ex)
{
return BadRequest(new {error = "Authentication Failed"});
}
}
Я также исправляю асинхронность / ожидание действия контроллера. Вам нужно использовать async Task<ActionResult>
вместо вашего ActionResult<string>
Комментарии:
1. Отличный ответ и работает «из коробки», за исключением того, что мой метод authError() возвращает ActionResult<string> (строку ошибки в формате json). Как мне сохранить это, если возвращаемый тип входа (returnUrl) — ActionResult или Task<ActionResult>?
2. Можете ли вы предоставить
AuthError
метод?3. Упрощено для краткости:
ActionResult<string> AuthError() { return "{ "error": "Authentication Failed" }"; }
4. Я думаю, вы можете использовать,
BadRequest(...)
которые возвращают 400 http-кода или использоватьOk(...)
с тем же объектом ошибки, если вам нужно повторно выполнить 200 http-кода. Я уже редактирую свой ответ.
Ответ №2:
Вместо перенаправления создайте свой собственный атрибут, наследуемый от AuthorizeAttribute
и переопределите OnAuthorization
метод. Таким образом, вам не нужно беспокоиться о перенаправлении.
Комментарии:
1. Можете ли вы предоставить пример метода переопределения
OnAuthorization
?