61 votes

Asp.Net Forms Authentication lors de l'utilisation de l'iPhone UIWebView

Je suis en train d'écrire un Asp.net MVC 2 application qui utilise l'Authentification par Formulaires et actuellement j'ai un problème avec notre application iPhone en ce qui concerne l'authentification/identification sur le web. Nous avons développé une simple application pour iPhone qui utilise la UIWebView de contrôle. À ce stade, tout ce que l'application n'est d'accéder à notre Asp.Net site web. Simple, non? Le problème, c'est que l'utilisateur ne peut pas obtenir au-delà de la page de connexion. La repro étapes sont les suivantes:

  • Ouvrez l'application iPhone.
  • L'application accède à la page d'accueil.
  • l'utilisateur n'est pas authentifié, de sorte qu'ils sont redirigés vers l'écran de connexion/page
  • L'utilisateur entre le nom d'utilisateur correct et le mot de passe. clique sur le bouton envoyer.
  • sur le côté serveur, l'utilisateur est authentifié et un cookie est généré et envoyé au client à l'aide de FormsAuthentication.GetAuthCookie.
  • Le serveur envoie redirect pour envoyer l'utilisateur vers la bonne page d'accueil.

Mais l'utilisateur est alors redirigé RETOUR à l'écran de connexion!

J'ai fait quelques poussées de débogage sur le présent et ce que je sais, c'est:

Le cookie est envoyé au client, et le client est de stocker le cookie. Vérifié cela dans l'iPhone débogueur et aussi en utilisant Javsascript pour afficher les données des cookies sur la page. Le cookie est envoyé vers le serveur. Vérifié cela dans le débogueur Visual Studio. C'est le bon cookie (c'est le même que celui qui a été défini). La propriété de l'Utilisateur.L'identité.IsAuthenticated renvoie la valeur false pour une raison quelconque, même si l'auth cookie est contenue dans l'objet de Requête. J'ai vérifié que l'application iPhone est configuré pour accepter les cookies, et ils sont sur le client.

Voici la drôle de chose: Il fonctionne très bien si vous ouvrez le navigateur Safari sur l'iPhone et accédez à notre site directement.

Il a le même comportement sur l'iPad trop dans qu'elle ne soit pas passé à l'écran de connexion. Cette repros sur les émulateurs, et sur les périphériques.

Ce site web a été testé avec IE 7 et 8, Safari (pour Windows), Blackberry, IEMobile 6.5, Phone 7 et il fonctionne à trouver. La seule circonstance qu'il ne veut pas travailler, est la UIWebView dans l'application iPhone.

44voto

Hunterwood Points 401

J'ai eu exactement le même problème, mais avec un autre appareil (NokiaN8), et retrace également le problème de dos de l'Agent Utilisateur.

IIS utilise des expressions régulières pour le match contre la chaîne de l'Agent Utilisateur. La racine du problème est qu'il n'ont pas de correspondance des expressions rationnelles pour le périphérique spécifique, et s'est retrouvé dans l'un des niveaux les plus bas de match, où les propriétés par Défaut ont été utilisés. Les propriétés par défaut a dit que le navigateur ne prend pas en charge les cookies.

Solution:

  1. Ajouter un dossier dans votre projet web nommé App_Browsers (cliquer droit sur le projet, choisir: Add > Add ASP.NET Folder > App_Browsers).
  2. Ajouter un fichier dans ce dossier (clic droit, choisir: Add > New Item). Le fichier peut avoir n'importe quel nom, mais il doit avoir l' .browser de la fin.
  3. Ajouter une bonne correspondance d'expression et la bonne capacités (ou ajouter des modifications à l' Default).

Deux exemples:

<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>

Ou de modifier la valeur par défaut:

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

Plus d'infos: Fichier de Définition de Navigateur de Schéma

42voto

Brian Y Points 638

La solution que nous avons trouvée consistait à créer un fichier (generic.browser) et à inclure ce fichier xml pour indiquer au serveur Web que "Mozilla" et les paramètres du navigateur par défaut devaient tous prendre en charge les cookies.

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

17voto

Scott Hanselman Points 13109

Ceci est corrigé dans ASP.NET 4.5 et tous les navigateurs sont supposés prendre en charge les cookies. Par conséquent, le fichier .browser supplémentaire ne sera pas nécessaire.

5voto

Jack Points 91

De la recherche que j'ai fait, la raison pour laquelle vous ne pouvez pas définir le User-Agent, c'est que la UIWebView est le réglage de l'User-Agent de la valeur juste avant d'envoyer la demande, c'est après que vous avez fait votre demande à partir de votre code.

L'astuce pour contourner ce problème est d'utiliser quelque chose qui s'appelle la "méthode swizzling", une avancée potentiellement dangereux, Objective-C concept qui permute une méthode standard avec un que vous fournissez. Le résultat final est que lorsque votre demande est envoyée et le code de la structure de l'ajout de l'Utilisateur-Agent, il sera trompé en utilisant la méthode que vous avez fournis.

Ce qui suit explique ce que j'ai fait pour mettre en œuvre cela, mais je ne suis pas Objective-C expert et vous suggère de faire quelques recherches pour vous familiariser avec la technique. En particulier, il y a un lien là expliquer mieux que moi ce qui se passe ici, mais pour le moment je ne peux pas le trouver.

1) Ajouter une catégorie sur NSObject pour permettre 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) la sous-classe NSMutableURLRequest pour permettre à l'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) Appeler la méthode statique de remplacement de la méthode. J'ai fait cet appel dans didFinishLaunchingWithOptions:

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

4), puis utilisé comme ça. (La connexion délégué enregistre les données dans un tableau mutable et puis configure manuellement la UIWebView à l'aide de son loadData méthode quand il finit de se charger).

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

3voto

goths Points 2412

J'ai eu exactement le même problème, recherché et consolidé une solution complète (à partir des réponses ci-dessus et d'autres discussions) ici: http://www.bloggersworld.com/index.php/asp-net-forms-authentication-iphone-cookies/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X