Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

29.01.2012, 18:41

[C#] WCF Rest-Service Authentifizierung - jQuery

Hallo,
ich habe folgendes Problem:
Ich möchte mich mit einem Rest Client beim WCF-Server authentifizieren, um anschließend den angebotene Service nutzen zu können. Für die Authentifizierung nutze ich BasisAuthenciation.

<webHttpBinding>
<binding name="BasicAuthentication" >
<!-- Basic Authenciation -->
<security mode="TransportCredentialOnly" >
<transport clientCredentialType="Basic" />
</security>
</binding>
</webHttpBinding>
<serviceBehaviors>
<behavior>
<!-- Custom Authenciation -->
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="GkServer.Security.CustomValidator, GkServer" />
</serviceCredentials>
</behavior>
</serviceBehaviors>

An sich ist das auch kein Problem, ich kann wunderbar über den Browser die Services nutzen. Jedoch ist das mit javascript nicht so leicht möglich. Folgender Ansatz:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
function drawTable(uri) {
    $.ajax({
        url: uri,
        dataType: 'json',
        type: 'GET',
        async: false,
        beforeSend: function (xhr) {
            xhr.setRequestHeader('Authorization', 'Basic ' + Base64.encode('test:test'));
        },
        error: function () { alert("error") },
        success: function (data) {
            // setup the new map and its variables
            var map = new google.visualization.DataTable();
            map.addRows(data.length);  // length gives us the number of results in our returned data
 
            var head = data[0];
            for (p in head) {
                if (typeof (head[p]) != 'object')
                    map.addColumn(typeof (head[p]), p);
            }
 
            // now we need to build the map data, loop over each result
            $.each(data, function (i, v) {
                var j = 0;
                for (item in v) {
                    if (typeof (v[item]) != 'object') {
                        map.setValue(i, j, v[item]);
                        j++;
                    }
                }
            });
 
            var table = new google.visualization.Table(document.getElementById('table'));
            table.draw(map);
        }
    });
}


Jedoch sendet das xhr Object eine Option-Request anstatt einer GET-Request:

OPTIONS http://gaia:8080/GkServer/articles?categoryId=2 HTTP/1.1
Host: gaia:8080
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://localhost:49551
Access-Control-Request-Headers: Origin, Authorization, Accept

Da der Link http://gaia:8080/GkServer/articles?categoryId=2 aber mit einer Get-Method gemappt ist und die Request kein Authorization-Header-Eintrag hat, kann diese Request natürlich nicht korrekt verarbeitet werden. Dementsprechend diese Fehlermeldung auf der Client-Seite:

Quellcode

1
2
OPTIONS http://gaia:8080/GkServer/articles?categoryId=2 401 (Unauthorized)
XMLHttpRequest cannot load http://gaia:8080/GkServer/articles?categoryId=2. Origin http://localhost:49551 is not allowed by Access-Control-Allow-Origin.

Folgende (manuell erstelle) Request funktioniert hingegen ohne Probleme:

GET http://gaia:8080/GkServer/articles?categoryId=1 HTTP/1.1
Authorization: Basic dGVzdDp0ZXN0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Hier erhalte ich als Ergebnis eine wunderbare XML-Seite mit den Artikeln.

Meine Frage ist, warum das xhr-Objekt überhaupt eine OPTION-Anfrage sendet und wie ich diese vorher beim WCF-Server abfangen und korrekt verarbeiten kann (Ich habe keine Global.asax oder *.svc Datei, da ich nicht vor habe die Services auf dem IIS zu hosten, sondern die Services selbst mit dem ServiceHost bereitstelle). Anzumerken ist, dass es nicht am CrossDomain-Problem liegt, das habe ich folgendermaßen gelöst:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
using GkServer.Model;
using System.ServiceModel.Web;
 
namespace GkServer.Service
{
    public class GkContextService : GkServer.Service.IGkContextService
    {
        public GkContextService()
        {
            WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Origin", "*");
            WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Methods", "POST, GET");
            WebOperationContext.Current.OutgoingResponse.Headers.Add("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept");
        }        /* Restliche Methoden */
    }
}


PS: Der Editor hat mich fast zur Weißglut gebracht, also seit bitte wegen der vllt. schlechten Formatierung etwas nachsichtig ;)

Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von »GreenPepper« (29.01.2012, 19:34)