Веб-приложение, созданное с помощью шаблона по умолчанию VS 2017, имеет следующий метод Startup.ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddAzureAd(options => Configuration.Bind("AzureAd", options))
.AddCookie();
services.AddMvc(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
})
.AddRazorPagesOptions(options =>
{
options.Conventions.AllowAnonymousToFolder("/Account");
});
}
Таким образом, фильтр "Авторизация" применяется глобально, даже для домашней страницы индекса (исключение составляют страницы / Account / AccessDenied и / Account / SignedOut, которые применяются [AllowAnonymous] в приведенном выше коде). Это означает, что когда приложение запускается, оно сразу переходит на страницу входа Microsoft, что хорошо для моего случая.
AccountController имеет следующий код:
[Route("[controller]/[action]")]
public class AccountController : Controller
{
[HttpGet]
public IActionResult SignIn()
{
var redirectUrl = Url.Page("/Index");
return Challenge(
new AuthenticationProperties { RedirectUri = redirectUrl },
OpenIdConnectDefaults.AuthenticationScheme
);
}
[HttpGet]
public IActionResult SignOut()
{
var callbackUrl = Url.Page("/Account/SignedOut", pageHandler: null, values: null, protocol: Request.Scheme);
return SignOut(
new AuthenticationProperties { RedirectUri = callbackUrl },
CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme
);
}
}
Здесь AccountController.Signin будет применять [Authorize] неявно, потому что фильтр Authorize применяется глобально. По-видимому, код не будет работать, если пользователь сначала не выйдет из системы и явно не запросит /account/signin
url. Но даже в этом случае первым делом является неявный фильтр [Authorize], и код запускается только после успешного входа пользователя. Итак, вопрос в том, какой смысл возвращать ChallengeResult, потому что пользователь должен был уже был аутентифицирован в тот момент? Может быть, просто перенаправить на страницу индекса, как показано ниже?
[HttpGet]
public IActionResult SignIn()
{
return RedirectToPage("/Index");
}
Или, как показано ниже, почему бы не применить [AllowAnonymous] к AccountController.SignIn, чтобы он запускался немедленно, когда пользователь запрашивает /account/signin
url?
[HttpGet]
[AllowAnonymous]
public IActionResult SignIn()
{
var redirectUrl = Url.Page("/Index");
return Challenge(
new AuthenticationProperties { RedirectUri = redirectUrl },
OpenIdConnectDefaults.AuthenticationScheme
);
}
Еще один вопрос. Я хочу выполнить некоторый код сразу после того, как пользователь войдет в систему. Куда поместить этот код, если AccountController.SignIn не запустится, если явно не запрошено? Шаблон по умолчанию создал другой класс, который называется AzureAdAuthenticationBuilderExtensions. Должен ли я подключиться к событиям OpenId в этом классе и поместить свой код в эти обработчики событий?