Delphi XE에서 DataSnap을 사용하여 REST 웹 서비스를 만들었습니다. XMLHttpRequest JavaScript 객체를 사용하여 서버 메소드를 호출하려고합니다. XMLHttpRequest Open 메소드의 네 번째 및 다섯 번째 선택적 매개 변수에 인증 용 사용자 이름과 암호를 전달합니다.OnUserAuthenticate가 DataSnap REST 서버에서 두 번 호출되는 이유는 무엇입니까?
DataSnap 서버를 Delphi에로드하고 IIS 7.5에 디버거를 연결하면 서버 메서드 중 하나를 호출하면 DSAuthenticationManager의 OnUserAuthenticate 이벤트가 두 번 호출되는 결과가 나타납니다.
첫 번째 호출에서 OnUserAuthenticate 이벤트 핸들러의 user 및 password 매개 변수는 빈 문자열입니다. 두 번째 호출에서는 XMLHttpRequest Open 메서드에서 전달한 사용자 이름과 암호가 해당 매개 변수에 나타납니다.
일단 사용자가 인증되면 XMLHttpRequest를 사용하는 서버 메서드에 대한 이후의 모든 호출은 사용자의 사용자 이름과 암호가 각각 User 매개 변수와 Password 매개 변수에 나타나는 OnUserAuthenticate 이벤트 처리기를 한 번 호출합니다.
많은 DataSnap 클래스의 소스 코드를 검사했는데이 효과가 발생할 수있는 코드를 찾지 못했습니다. 이로 인해 브라우저 나 IIS에서이 동작이 발생할 수 있다고 생각하게되었습니다.
첫 번째 서버 메서드 호출시 OnUserAuthenticate가 두 번 호출되는 이유는 무엇입니까?
Mat DeLong의 대답에 대한 응답으로, 저는 서버 메소드를 호출하기 위해 사용하는 일반 함수 중 하나를 보여주고 있습니다. 이 특별한 방법은 동기 호출을 만든다. baseURL 매개 변수는 일반적으로 http://mydomain.com/myservice/myservice.dll/datasnap/rest/tservermethods1과 유사한 문자열이며 메서드는 myservermethod가 될 수 있습니다. 추가 파라미터는 서버 방식으로 파라미터를 전달하는 데 사용된다
function getJSONSync(baseURL, method) {
var request = new XMLHttpRequest();
var url = baseURL + method;
for (var i= 2; i < arguments.length; i++) {
url += "/" + arguments[i];
}
request.open("GET", encodeURI(url), false);
request.send(null);
if (request.status != 200) {
throw new Error(request.statusText);
}
return jQuery.parseJSON(request.responseText);
}
편집 렉스 리는 제 요청에 실패 할 경우, IIS는 기본 인증을 사용하는 것이 올바른 것으로 나타난다. 또한 Mat는 OnUserAuthenticate가 세션 당 한 번만 호출되어야한다는 것이 맞습니다. 그가 제공 한 링크를 검토 한 결과 세션 ID를 캡처하고 반환하지 못했습니다. 이번에는 비동기 적으로 작동하는 코드 예제가 있습니다. 그것은 세션 ID를 캡처하여 숨겨진 필드에 저장합니다. 그런 다음 Pragma 헤더의 각 후속 호출에서 해당 세션 ID를 다시 전달합니다.
function getJSONAsync(callback, baseURL, method) {
var request = new XMLHttpRequest();
var timedout = false;
request.onreadystatechange = function() {
if (request.readyState !== 4) { return }
if (timedout) { return }
if (request.status >= 200 && request.status < 300)
{
callback(jQuery.parseJSON(request.responseText));
//store the sessionid in a hidden field
$("#sessionid").val(request.getResponseHeader('Pragma').split(',')[0].split("=")[1]);
}
}
var url = baseURL + method;
for (var i= 3; i < arguments.length; i++) {
url += "/" + arguments[i];
}
request.open("GET", encodeURI(url), true);
//pass the sessionid in the Pragma header, if available
if (! $("#sessionid").val() == "") {
request.setRequestHeader("Pragma", "dssession="+$("#sessionid").val());
}
//time out if request does not complete in 10 seconds
var timer = setTimeout(function() { timedout = true; request.abort(); }, 10000);
request.send(null);
}
편집 : 내가 처음이 두 코드 샘플을 게시 할 때 나는 XMLHttpRequest의 open 메소드의 네 번째와 다섯 번째 매개 변수 샘플 사용자 이름과 암호를 포함. 테스트 중에 명시 적으로이 값을 전달했습니다. 이와 같은 매개 변수를 전달하는 것은 좋지 않으므로이 편집에서 매개 변수를 제거했습니다. 이 암호를 생략하고 다른 메소드 (예 : 첫 번째 REST 서버 메소드 호출의 머리글과 같은)를 사용하여 암호를 전달하지 않으면 브라우저에 사용자에게이 정보를 묻는 대화 상자가 표시됩니다. 사용자 이름과 암호가 제공되면 브라우저는 나머지 세션 동안이 정보를 기억합니다. 브라우저를 닫았다가 다시 열고 다른 REST 서버 메소드를 호출하면 사용자 이름과 비밀번호를 다시 요구 받게됩니다. 물론 이것은 OnUserAuthenticate 이벤트 처리기를 통해 유효하지 않은 사용자를 거부하고 있다고 가정합니다.
이것이 올바른 것으로 보입니다. wireshark를 사용하여 패킷을 검사했습니다. 첫 번째 요청에는 기본 인증 헤더 정보가 포함되지 않지만 두 번째 요청에는 기본 인증 헤더 정보가 포함되지 않습니다. 감사! –