HttpWebRequest (NTLM Authentifikation)

  • HttpWebRequest (NTLM Authentifikation)

    Hi Leute,

    ich möchte ein http Request absetzen und die Daten im JSON Format zurückbekommen. Dies ist auch soweit kein Problem.
    Der Server mit dem ich mich verbinden möchte nutzt jedoch die NTLM Authentifikation. Zusätzlich muss ich dem Header mitgeben, das die Daten im Json Format zurückgegeben werden sollen. Da ich mich noch nicht so gut mit Objectiv-C auskenne benötige ich an diesem Punkt eure Hilfe. In c# würde ich das ganze wie folgt umsetzen:

    Quellcode

    1. var svcUri = new Uri("http://....");
    2. var WebRequ = WebRequest.Create(svcUri) as HttpWebRequest; WebRequ.Accept = "application/json;odata=verbose";
    3. var netwCredential = new NetworkCredential(User,pw);
    4. var CredentCach = new CredentialCache();
    5. CredentCach.Add(svcUri, "NTLM", netwCredential);
    6. WebRequ.PreAuthenticate = true; WebRequ.Credentials = CredentCach;
    7. WebResponse WebRespon = WebRequ.GetResponse();

    (Vielleicht erklärt ja der c# code etwas was ich meine :P )

    Wie baue ich eine solche Verbindung in Objectiv-C auf?

    Vielen Dank für eure Hilfe vorab schon mal…..

    Grüße

    Nils
  • AFNetworking Json NTLM

    Hallo,
    erst einmal vielen Dank für die Antwort macmoonshine!!

    Leider bring mich das nicht weiter, da Trotz User und Passwort in der URL der Error 401 zurückgeben wird.
    Ich denke daher das ich mit Credentials arbeiten muss.

    Vielleicht ist das Thema dieses Eintrages schlecht gewählt den mein ursprünglicher Plan ist es mit dem AFNetworking Framework Json Daten zu konsumieren. Hierfür gibt es auch ein gutes Tutorial ("raywenderlich.com/30445/afnetworking-crash-course").

    Mir ist nur nicht klar wie ich die Authentifizierung per NTLM hier mit einbauen kann. In meinen online recherchen ist mir leider auch nichts aufgefallen, was mir dabei hilft.

    Grüße
    Nils
  • Nils% schrieb:

    Mir ist nur nicht klar wie ich die Authentifizierung per NTLM hier mit einbauen kann. In meinen online recherchen ist mir leider auch nichts aufgefallen, was mir dabei hilft.

    Das Problem ist nicht das Framework; Du kannst auch AFNetworking nehmen, wenn Du unbedingt willst. Das Problem ist in der Regel das Protokoll. Du musst für die Authentifizierung irgendwelche bestimmten Header in irgendeinem vorgegebenen Format mitschicken. Du solltest erst mal rausbekommen, wie dieser Anfrage- und ggf. der Antwortheader aussehen muss. Dann kann man darüber sprechen, wie man das in Objective-C gießt, und ob dafür ein Framework neben Foundation notwendig ist.

    Wenn ich den C#-Code richtig verstehe, hat der Header folgende Einträge:

    Quellcode

    1. Accept: application/json;odata=verbose
    2. PreAuthenticate: true
    3. Credentials = ...

    Diesen Header kannst Du beispielsweise so zusammenbauen:

    Quellcode

    1. NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:theURL];
    2. [theRequest setValue:@"application/json;odata=verbose" forHTTPHeaderField:@"Accept"];
    3. [theRequest setValue:@"true" forHTTPHeaderField:@"PreAuthenticate"];
    4. [theRequest setValue:... forHTTPHeaderField:@"Credentials"];
    „Meine Komplikation hatte eine Komplikation.“
  • Hi,

    bei unserem iPad Projekt an den Schulen haben wir massive Probleme über den ISA Server ins Neuland zu kommen. Mal klappt die Authentifizierung am Proxy und dann aus irgendwelchen Gründen will der ISA bei jeder Datei die geladen wird Username und Passwort haben. Irgendwann beruhigt er sich wieder, und dann geht es wieder ne Zeit lang - Microsoft halt. Wär ja sonst auch zu banal mit dem HTTP Proxy.

    Scheint also mit iOS etwas problematisch zu sein.

    Ich hab Kontakt zu nem Apple Ingenieur und der ist jetzt erst mal auf NTLM als Ursache gekommen.

    Es wird zwar nicht viel bringen, weil es hier ehr darum geht, der Windows Seuche das NTLM auszutreiben, aber hier mal die Mail, vielleicht helfen die Links ja irgendwie:

    ###########
    Hallo Herr Kress,

    demnach verstärkt sich der Eindruck, dass der ISA Server die Ursache ist. Gibt es hierzu bei Microsoft ein Support Ticket, oder haben Sie bei uns einen Case, auch Bug Report, eröffnet?

    Interessant wäre natürlich auch, ob Sie anstatt NTLM andere Authentifizierungsverfahren getestet haben, da sich das Problem in den Einstellungen des Proxies manifestiert, speziell in der Verwendung von NTML für die Authentifizierung. Auch andere Systeme, wie Mozilla haben diese Probleme (bugzilla.mozilla.org/show_bug.cgi?id=318253). Vergleichen Sie hierzu auch

    technet.microsoft.com/en-us/li…996225%28EXCHG.65%29.aspx.
    bzw.
    sysadminlab.net/exchange/outlo…-authentication-explained

    Hierzu sollten Sie ggf. eine Alternative zu NTLM wählen, bzw. Caching verwenden, vergleichen sie auch technet.microsoft.com/en-us/library/bb794722.aspx

    Alternativ sollten Sie auch einen Blick auf den NTLM Authorization Proxy Server ntlmaps.sourceforge.net werfen, welcher auch dem ISA vorgeschalten werden kann.

    ###############

    Gruß
    Manfred

    P.S.: Ich kann die Scheiße nicht mehr sehen. Und bevor ich mich durchs Windows quäle, versuche ich jetzt erst mal einen Squid vor jeden ISA zu bauen - bescheuerter geht's nicht.
    Seminare, Artikel, Code. ObjectiveCeeds - alles für die Apfelzucht.
  • Hi,

    leider habe ich es immer noch nicht ganz verstanden.....
    Mein Code sieht nun wie folgt aus:

    Quellcode

    1. NSURLCredential *mycredential = [NSURLCredential credentialWithUser:@"user" password:@"pw" persistence:NSURLCredentialPersistencePermanent];
    2. NSURLProtectionSpace *myprotectSpac = [[NSURLProtectionSpace alloc] initWithHost:@"Server" port:7048 protocol:@"http" realm:nil authenticationMethod:NSURLAuthenticationMethodNTLM];
    3. NSDictionary *myCredntStor = [[NSURLCredentialStorage sharedCredentialStorage] credentialsForProtectionSpace:myprotectSpac];
    4. NSLog(@"Test1");
    5. NSMutableURLRequest *Myrequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://Server:7048/xxxx/ODATA/"]];
    6. [Myrequest setValue:@"application/json;odata=verbose" forHTTPHeaderField:@"Accept"];
    7. [Myrequest setValue:@"true" forHTTPHeaderField:@"PreAuthenticate"];
    8. NSLog(@"Test2");
    9. [NSURLConnection sendAsynchronousRequest:Myrequest
    10. queue:[NSOperationQueue mainQueue]
    11. completionHandler:^(NSURLResponse* response, NSData *data, NSError* error) {
    12. NSError *MyError = nil;
    13. if (data!=nil) {
    14. NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data
    15. options:kNilOptions error:&MyError];
    16. NSArray *JsonDataArr = json[@"loans"];
    17. if (MyError != nil) {
    18. NSLog(@"Error %@", [MyError localizedDescription]);
    19. } else {
    20. NSLog(@"Load: %@",JsonDataArr);
    21. }
    22. }
    23. NSLog(@"Test3");
    24. }];
    Alles anzeigen


    Die Ausgabe des Logs:

    Quellcode

    1. 2013-08-28 00:25:30.788 Odata_To_Json[6248:c07] Test1
    2. 2013-08-28 00:25:30.789 Odata_To_Json[6248:c07] Test2
    3. 2013-08-28 00:25:30.809 Odata_To_Json[6248:c07] Error The operation couldn’t be completed. (Cocoa error 3840.)
    4. 2013-08-28 00:25:30.810 Odata_To_Json[6248:c07] Test3


    Wie sage ich dem Request das die oben erzeugten Credentials verwendet werden sollen?
    Die Einstellung für den Header müssten so passen (Danke!!!) Der c# Quellcode funktioniert ja auch!
    Langsam verzweifele ich an der einfachen Abfrage der Daten :-(

    Eine andere Authentifizierung kann ich leider auch nicht verwenden.

    Grüße

    Nils
  • Nils% schrieb:

    Wie sage ich dem Request das die oben erzeugten Credentials verwendet werden sollen?

    Weißt Du denn wie die Credentials aussehen sollen und wie sie kodiert sind? Da hilft nur ein Blick ins Protokoll. Dazu findest Du einiges im Netz.

    Wahrscheinlich kannst Du sie über den NSURLCredentialStorage verwalten. Dazu musst Du jedoch wissen, wie sie aussehen.
    „Meine Komplikation hatte eine Komplikation.“
  • Hallo,
    ähm also eigentlich dachte ich, ich hätte die schon passen
    angelegt…
    [code]
    NSURLCredential *mycredential = [NSURLCredential credentialWithUser:@"user" password:@"pw" persistence:NSURLCredentialPersistencePermanent];
    NSURLProtectionSpace *myprotectSpac = [[NSURLProtectionSpace alloc] initWithHost:@"Server" port:7048 protocol:@"http" realm:nil authenticationMethod:NSURLAuthenticationMethodNTLM];
    NSDictionary *myCredntStor = [[NSURLCredentialStorage sharedCredentialStorage] credentialsForProtectionSpace:myprotectSpac];
    [code/]


    Irgendwie habe ich nicht ganz das passende im Web gefunden
    kannst du mir ein gutes HowTo oder so empfehlen?


    Grüße
    Nils
  • Und es geht doch :)

    Quellcode

    1. [super viewDidLoad];
    2. NSURL *locationOfWebService = [NSURL URLWithString:urlString];
    3. NSMutableURLRequest *theRequest = [[NSMutableURLRequest alloc]initWithURL:locationOfWebService];
    4. [theRequest setValue:@"application/json;odata=verbose" forHTTPHeaderField:@"Accept"];
    5. NSURLConnection *connect = [[NSURLConnection alloc]initWithRequest:theRequest delegate:self];
    6. if (connect) {
    7. webData = [[NSMutableData alloc]init];
    8. NSLog(@"Ja");
    9. }
    10. else {
    11. NSLog(@"No Connection established");
    12. }
    Alles anzeigen

    wenn mann dann eine NSURLConnection delegate Methode anlegt:

    Quellcode

    1. -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    2. {
    3. [webData setLength: 0];
    4. }
    5. -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    6. {
    7. [webData appendData:data];
    8. }
    9. -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    10. {
    11. NSLog(@"ERROR with theConenction %@",error);
    12. [connection release];
    13. [webData release];
    14. }
    15. -(BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
    16. {
    17. return YES;
    18. }
    19. -(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
    20. {
    21. NSURLCredential *credential = [NSURLCredential credentialWithUser:@"user" password:@"pw" persistence:NSURLCredentialPersistenceForSession];
    22. [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
    23. }
    24. -(void)connectionDidFinishLoading:(NSURLConnection *)connection
    25. {
    26. NSString *theJson = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
    27. NSLog(@"%@",theJson);
    28. convertToStringData = [[NSString alloc] initWithData:webData encoding:NSUTF8StringEncoding];
    29. [connection release];
    30. }
    Alles anzeigen



    Und das sind die Daten als Json request ;)
    Danke euch!!!!!

    Vielleicht kann das ja noch mal jemand gebrauchen :P