Excepção no redireccionamento dos formulários de autenticação em ASP.NET

Uma excepção é lançada quando se usa o método FormsAuthentication.RedirectFromLoginPage com alguns URLs de retorno que são marcados como inválidos, embora não o sejam. Este método é usado para autenticar e redireccionar um utilizador validado a partir da página de login.

Este problema ocorre quando utilizadores não autenticados tentam aceder a uma página que requer autenticação e cujo URL é parecido com o seguinte:

http://www.example.com/subsite/page.aspx?param=http://www.example.com/subsite2/something/else.aspx

Reparem que o URL inclui outro URL como parâmetro.

O utilizador é de seguida redireccionado para a página de login e o ASP.NET adiciona automaticamente o parâmetro do URL de retorno. O URL da página de autenticação fica então no seguinte formato:

http://www.example.com/login.aspx?ReturnUrl=/subsite/page.aspx?param=http://www.example.com/subsite2/something/else.aspx

Ou seja, é basicamente um URL com um URL de retorno que inclui, nele próprio, um URL como parâmetro query string.

Os métodos internos usados pelo método FormsAuthentication.RedirectFromLoginPage assumem que este URL é inválido e lançam a seguinte excepção:

System.Web.HttpException The return URL specified for request redirection is invalid.
 at System.Web.Security.FormsAuthentication.GetReturnUrl(Boolean useDefaultIfAbsent)
 at System.Web.Security.FormsAuthentication.RedirectFromLoginPage(String userName, Boolean createPersistentCookie, String strCookiePath)
 at System.Web.Security.FormsAuthentication.RedirectFromLoginPage(String userName, Boolean createPersistentCookie)

Uma forma de contornar este problema é fazer duas chamadas separadas:

FormsAuthentication.SetAuthCookie(username, false);
Page.Response.Redirect(Page.Request["ReturnUrl"]);

A primeira chamada define o cookie de autenticação e a segunda redirecciona o utilizador para o URL de retorno

No entanto, é melhor não fazer desta forma, porque o URL de retorno pode estar vazio e, nesses casos, o utilizador deve ser redireccionado para o DefaultUrl. Uma solução final poderá ser:

string url = Page.Request["ReturnUrl"] as string;
 
if (!string.IsNullOrEmpty(url))
{
    FormsAuthentication.SetAuthCookie(username, false);
    Page.Response.Redirect(url);
}
else
{
    // there is no URL, RedirectFromLoginPage can be safely used to redirect to the default URL
    FormsAuthentication.RedirectFromLoginPage(username, false);
}

Devem colocar isto num método à parte e adicionar try/catch e logging como necessário.

Nuno Freitas
Publicado por Nuno Freitas em 30 julho, 2013

Artigos relacionados