Estou criando um site multilocação que hospeda páginas para clientes. O primeiro segmento da URL será uma string que identifica o cliente, definida em Global.asax usando o seguinte esquema de roteamento de URL:
"{client}/{controller}/{action}/{id}"
Isso funciona bem com URLs como / foo / Home / Index.
No entanto, ao usar o atributo [Autorizar], desejo redirecionar para uma página de login que também usa o mesmo esquema de mapeamento. Portanto, se o cliente for foo, a página de login seria / foo / Account / Login em vez do redirecionamento fixo / Account / Login definido em web.config.
O MVC usa um HttpUnauthorizedResult para retornar um status 401 de não autorizado, que presumo que faz com que o ASP.NET redirecione para a página definida em web.config.
Então, alguém sabe como substituir o comportamento de redirecionamento de login do ASP.NET? Ou seria melhor redirecionar em MVC criando um atributo de autorização personalizado?
EDIT - Resposta: após algumas pesquisas na fonte .Net, decidi que um atributo de autenticação personalizado é a melhor solução:
public class ClientAuthorizeAttribute: AuthorizeAttribute
{
public override void OnAuthorization( AuthorizationContext filterContext )
{
base.OnAuthorization( filterContext );
if (filterContext.Cancel && filterContext.Result is HttpUnauthorizedResult )
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary
{
{ "client", filterContext.RouteData.Values[ "client" ] },
{ "controller", "Account" },
{ "action", "Login" },
{ "ReturnUrl", filterContext.HttpContext.Request.RawUrl }
});
}
}
}
Respostas:
Eu acho que o principal problema é que se você vai pegar carona na classe ASP.NET FormsAuthentication integrada (e não há uma boa razão para não fazer isso), algo no final do dia vai chamar
FormsAuthentication.RedirectToLoginPage()
que vai para ver o URL configurado. Há apenas um URL de login, sempre, e é assim que eles o criaram.Minha tentativa de resolver o problema (possivelmente uma implementação de Rube Goldberg) seria deixá-lo redirecionar para uma única página de login na raiz compartilhada por todos os clientes, digamos / conta / login. Esta página de login não exibiria nada; ele inspeciona o parâmetro ReturnUrl ou algum valor que obtive na sessão ou um cookie que identifica o cliente e usa isso para emitir um redirecionamento 302 imediato para a página específica / cliente / conta / login. É um redirecionamento extra, mas provavelmente não perceptível e permite que você use os mecanismos de redirecionamento integrados.
A outra opção é criar seu próprio atributo personalizado conforme você descreve e evita qualquer coisa que chame o
RedirectToLoginPage()
método naFormsAuthentication
classe, já que você o substituirá por sua própria lógica de redirecionamento. (Você pode criar sua própria classe semelhante.) Como é uma classe estática, não conheço nenhum mecanismo pelo qual você possa simplesmente injetar sua própria interface alternativa e fazê-la funcionar magicamente com o atributo [Autorizar] existente, que golpes, mas as pessoas já fizeram coisas semelhantes antes .Espero que ajude!
fonte
Application_AuthenticateRequest
(veja minha resposta abaixo).Na versão RTM da ASP.NET MVC, a propriedade Cancel está ausente. Este código funciona com ASP.NET MVC RTM:
Edit: Você pode querer desabilitar o loginUrl de autenticação de formulários padrão em web.config - no caso de alguém esquecer que você tem um atributo personalizado e usar o atributo embutido [Autorizar] por engano.
Modifique o valor em web.config:
Em seguida, execute um método de ação 'ERROR' que registra um erro e redireciona o usuário para a página de login mais genérica que você possui.
fonte
Minha solução para esse problema foi uma
ActionResult
classe personalizada :fonte
Ainda assim, se alguém decidir usar o ASP.NET FormsAuthentication embutido, pode substituí-lo
Application_AuthenticateRequest
daGlobal.asax.cs
seguinte maneira:fonte