2010-11-11 23 views
61

Estoy escribiendo una aplicación Asp.net MVC 2 que usa la Autenticación de formularios y actualmente estoy teniendo un problema con nuestra aplicación de iPhone con respecto a la autenticación/inicio de sesión en la web. Hemos desarrollado una aplicación de iPhone simple que utiliza el control UIWebView. En esta etapa, todo lo que hace la aplicación es navegar a nuestro sitio web Asp.Net. Simple, ¿verdad? El problema es que el usuario no puede pasar de la página de inicio de sesión. Los pasos de reproducción son:Asp.Net Autenticación de formularios al usar el iPhone UIWebView

  • Abra la aplicación para iPhone.
  • La aplicación navega a la página de inicio.
  • el usuario no está autenticado, por lo que se le redirige a la pantalla/página de inicio de sesión
  • El usuario ingresa el nombre de usuario y la contraseña correctos. clics enviar.
  • en el lado del servidor, el usuario se autentica y se genera una cookie y se envía al cliente utilizando FormsAuthentication.GetAuthCookie.
  • Los envíos del servidor se redireccionan para enviar al usuario a la página de inicio correcta.

Pero el usuario es redirigido a continuación VOLVER a la pantalla de inicio de sesión!

he hecho algunas extensa depuración en esto y lo que sí sé es:

La cookie está siendo enviado al cliente, y el cliente es el almacenamiento de la cookie. Verificado esto en el depurador de iPhone y también mediante el uso de Javsascript para mostrar datos de cookies en la página. La cookie se envía de vuelta al servidor. Verificado esto en el depurador de Visual Studio. Es la cookie correcta (es la misma que se configuró). La propiedad User.Identity.IsAuthenticated devuelve false por algún motivo, aunque la cookie de autenticación esté contenida en el objeto Request. He verificado que la aplicación de iPhone está configurada para aceptar cookies, y están en el cliente.

Aquí está lo gracioso: funciona bien si abre el navegador Safari en el iPhone y va directamente a nuestro sitio.

Tiene el mismo comportamiento en el iPad porque no pasa de la pantalla de inicio de sesión. Esto repros en los emuladores y en los dispositivos.

Este mismo sitio web ha sido probado con IE 7-8, Safari (para Windows), Blackberry, IEMobile 6.5, Phone 7 y funciona find. La única circunstancia en la que no funciona es UIWebView en la aplicación iPhone.

+0

¿Ha logrado encontrar una solución a este problema? Estoy enfrentando el mismo problema ... :( –

+0

Sí, logramos encontrar una solución. Le pediré al desarrollador que resolvió el problema que publique su solución, ya que él la entiende mejor que yo. –

+0

Indique el solución ya que estoy enfrentando el mismo problema. Gracias. – Neal

Respuesta

42

La solución que encontramos fue la creación de un archivo (generic.browser) e incluir esto xml para decirle al servidor web que "Mozilla" y la configuración predeterminada del navegador deben ser compatibles con las cookies.

<browser refID="Mozilla" > 
    <capabilities> 
     <capability name="cookies" value="true" /> 
    </capabilities> 
</browser> 
+0

Gracias por la muestra. Pude usar esto y compararlo con algunos otros archivos en la carpeta config y obtener lo que necesitaba. No estoy seguro si puede usar el mismo nombre que una definición de navegador existente, así que creé generic2.browser solo para estar seguro. ¡¡¡Gracias de nuevo!!! – Neal

+0

Al agregar la entrada predeterminada con cookies = true se solucionó el problema para mí. – Sam

+0

FYI: La entrada predeterminada no es necesaria, ya es verdadera. –

0
  1. ¿Se ha especificado un DestinationPageUrl en el marcado?

  2. ¿Ha especificado la URL predeterminada en web.config?

Ejemplo web.config

<authentication mode="Forms"> 
    <forms loginUrl="~/Login.aspx" defaultUrl="~/CustomerArea/Default.aspx"/> 
</authentication> 

Ejemplo DestinationPageUrl

<asp:Login ID="Login" runat="server" DestinationPageUrl="~/Secret/Default.aspx" /> 

Por último ¿Has mirado en la masa y ver si realmente existe la cookie de sesión?

Where are an UIWebView's cookies stored?

+0

Gracias por las sugerencias en ASP.NET. Las probaré. Re. cookies, sí, están configuradas y enviadas correctamente como se describe en el problema –

+0

No sé exactamente dónde está almacenando UIWebView las cookies. Sé que cada aplicación en iOS tiene su propio caché y almacenado de cookies. Sí, he verificado que las cookies se están almacenando en el dispositivo, y están siendo enviado de vuelta al servidor también. –

4

De la investigación que hice, la razón por la que no se puede establecer el User-Agent es que el UIWebView está fijando el valor de User-Agent justo antes de que envía la solicitud, es decir, después de has hecho tu pedido desde tu código.

El truco para evitar este problema es usar algo llamado "método swizzling", un concepto Objective-C avanzado y potencialmente peligroso que intercambia un método estándar con uno que usted proporciona. El resultado final es que cuando se envía su solicitud y el código de la infraestructura agrega el User-Agent, se lo engañará utilizando el método que proporcionó.

A continuación se explica lo que hice para implementar esto, pero no soy un experto en Objective-C y le sugiero que investigue un poco para familiarizarse con la técnica. En particular, había un enlace explicando mejor que yo lo que está pasando aquí, pero por el momento no puedo encontrarlo.

1) Agregue una categoría en NSObject para permitir swizzling.

@interface NSObject (Swizzle) 

+ (BOOL) swizzleMethod:(SEL)origSelector withMethod:(SEL)newSelector; 

@end 

@implementation NSObject (Swizzle) 


+ (BOOL) swizzleMethod:(SEL) origSelector withMethod:(SEL)newSelector 
{ 
    Method origMethod= class_getInstanceMethod(self, origSelector); 
    Method newMethod= class_getInstanceMethod(self, newSelector); 

    if (origMethod && newMethod) 
    { 
     if (class_addMethod(self, origSelector, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) 
     { 
      class_replaceMethod(self, newSelector, method_getImplementation(origMethod), method_getTypeEncoding(origMethod)); 
     } 
     else { 
      method_exchangeImplementations(origMethod, newMethod); 
     } 
     return YES; 
    } 
    return NO; 
} 
@end 

2) Subclase NSMutableURLRequest para permitir que el swizzle:

@interface NSMutableURLRequest (MyMutableURLRequest) 

+ (void) setupUserAgentOverwrite; 

@end 
@implementation NSMutableURLRequest (MyMutableURLRequest) 

- (void) newSetValue:(NSString*)value forHTTPHeaderField:(NSString*)field 
{ 
    if ([field isEqualToString:@"User-Agent"]) 
    { 
     value = USER_AGENT; // ie, the value I want to use. 
    } 
    [self newSetValue:value forHTTPHeaderField:field]; 
} 
+ (void) setupUserAgentOverwrite 
{ 
    [self swizzleMethod:@selector(setValue:forHTTPHeaderField:) 
      withMethod:@selector(newSetValue:forHTTPHeaderField:)]; 

} 

@end 

3) Llame al método estático para intercambiar a cabo el método. Hice esta llamada en didFinishLaunchingWithOptions:

// Need to call this method so that User-Agent get updated correctly: 
[NSMutableURLRequest setupUserAgentOverwrite]; 

4) y luego se usa como este. (El delegado de conexión guarda los datos en una matriz mutable y luego configura manualmente UIWebView utilizando su método loadData cuando termina de cargarse).

- (void)loadWithURLString:(NSString*)urlString 
{ 
    NSURL *url = [NSURL URLWithString:urlString]; 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 
_connection = [NSURLConnection connectionWithRequest:request delegate:self]; 
[_connection start]; 
} 
+1

¡Solucionó el problema! ¡Gracias amigo! –

+0

Para agregar a la respuesta, descubrí que ASP.NET no está contento con la cadena "Mozilla" en el agente de usuario, pero está bien cuando sigue la cadena "Versión/x.x Safari". Y es por eso que la cadena de agente de usuario proporcionada por UIWebView falló, mientras que la que proporcionó Safari móvil pasó. Silly ASP.NET ... –

+1

William, tiene razón sobre el problema con "mozilla" en el user-agent. Si mira la respuesta aceptada, hay información sobre cómo abordar esto en el lado del servidor. Pudimos deshacer todo el código de nuestro iPhone que implicaba piratear el agente de usuario porque el servidor ahora reconocería las cookies. –

44

Tuve exactamente el mismo problema, pero con otro dispositivo (NokiaN8), y también remonté el problema hasta el User-Agent.

IIS utiliza expresiones regulares para hacer coincidir con la cadena de User-Agent. La raíz del problema era que no tenía expresiones regulares coincidentes para el dispositivo específico y terminaba en uno de los niveles más bajos de coincidencia, donde se usaban las propiedades predeterminadas. Las propiedades predeterminadas indicaban que el navegador no admitía cookies.

Solución:

  1. añadir una carpeta en su proyecto web llamado App_Browsers (haga clic con el proyecto, elija: Add > Add ASP.NET Folder > App_Browsers).
  2. Agregue un archivo en esa carpeta (haga clic con el botón derecho, elija: Add > New Item). El archivo puede tener cualquier nombre, pero debe tener el final .browser.
  3. Agregue una buena expresión coincidente y las capacidades correctas (o agregue cambios al Default).

Dos ejemplos:

<browsers> 
    <browser id="NokiaN8" parentID="Mozilla"> 
    <identification> 
     <userAgent match="NokiaN8" /> 
    </identification> 
    <capabilities> 
     <capability name="browser" value="NokiaN8" /> 
     <capability name="cookies" value="true" /> 
    </capabilities> 
    </browser> 
</browsers> 

o cambiar el valor por defecto:

<browsers> 
    <browser refID="Default"> 
    <capabilities> 
     <capability name="cookies" value="true" /> 
    </capabilities> 
    </browser> 
</browsers> 

Más información: Browser Definition File Schema

+1

Lo curioso es que si cambiamos el User-Agent a "bla, bla, bla" realmente funcionó. Fue solo el User-Agent específico que la vista del navegador web incorporado utilizada en el iPhone que estaba fallando. Parecía que el servidor IIS no solo se estaba adaptando a un navegador desconocido, sino que realmente se estaba ahogando en la cadena User-Agent. –

+1

Descubrimos que el problema era que en ASP.Net 4.0, el análisis del agente de usuario se hacía de tal manera que el control UIWebView se identificaba como el navegador "Mozilla", ya que no había referencias a Safari en el Agente de usuario. Cuando miré los diversos archivos .browser en el servidor, encontré que el archivo que contiene la coincidencia para los navegadores Mozilla (generic.browser) contenía la línea . Por lo tanto, el servidor ASP.Net consideraba que todos los navegadores Mozilla no admitían cookies. –

+1

¿Puede alguien proporcionar la definición exacta del navegador que necesito agregar a App_Browsers para que pueda hacer que mi UIWebView funcione en asp.net 4? Nadie puede iniciar sesión en mi sitio, etc. mientras esté roto. Gracias. – Neal

16

Este se fija en ASP.NET 4.5 y todos los navegadores se supone soportar cookies, por lo que no será necesario el archivo .browser adicional.

+1

He intentado todos los enfoques en esta página, Y me estoy ejecutando en .NET 4.5 y todavía no funciona. http://stackoverflow.com/questions/24781648/cookies-not-saved-between-browser-sessions-on-ios – ganders

0

La razón de que esto ocurra al parecer tiene que ver con el hecho de que si el el usuario agente no se conoce, se supone que el navegador no acepta cookies (como otros han respondido), y en su lugar IIS pone el valor de ASPXAUTH en la URL.

Sin embargo, el sistema de enrutamiento MVC aparentemente se perdió esa posibilidad, lo cual es claramente un error, y por lo tanto se está desordenando.

Si bien la adición del .browser con un agente de usuario personalizado resuelve el problema, no garantiza que otros agentes de usuario también se resuelvan, y de hecho, he encontrado que el navegador K9 para Android también tiene este problema, y como tal, es solo una solución si uno tiene un sistema de registro tal como elmeh para rastrear tales errores.

Por otro lado, al agregar un valor predeterminado aparece la pregunta si es cierto que todos los navegadores aceptan cookies, que aparentemente es la razón por la que IIS no lo asume.

Sin embargo además de añadir explicitamente los agentes de usuario se puede añadir en las RegiterRoutes Global.asax() método un controlador explícito de ignorarlo, como sigue:

  routes.MapRoute(
      "CookieLess", // Route name 
      "(F({Cookie}))/{controller}/{action}/{id}", // URL with parameters 
      new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults 
     ); 

Sin embargo, en este caso uno tendrá que copiar todas las entradas de ruta coinciden con la situación sin cookies, a menos que una esté a punto de escribir un manejador de ruta personalizado.

O podemos utilizar la ruta anterior sin cookies para enviar al usuario a una página de error explicando que su navegador no es compatible por el momento, y enviar una alerta al maestro web con el agente de usuario para manejarlo .

Cuestiones relacionadas