2011-01-08 48 views
0

我試圖讓我的Flex應用程序在這裏使用的說明與谷歌進行身份驗證:403錯誤,當試圖從Flash應用程序(的AuthSub針對ActionScript)訪問谷歌的AuthSub

http://code.google.com/apis/gdata/docs/as-authsub.html

我抄的例子那裏,我試圖讓它工作。我正在我的一個LOCA服務器上的應用程序,所以我已經改變了下一個參數:

authSubParams['next'] = 'http://localhost/AuthSub.html'; 

獲得的第一個標記工作正常,但當我試圖讓長住令牌我得到一個錯誤:

getLongLivedToken: singleUseToken: 1%2Fa... 
onHttpStatus: [HTTPStatusEvent type="httpStatus" bubbles=false cancelable=false eventPhase=2 status=403 responseURL=null] 
onGetTokenFailed: Error #2032: Stream Error. URL: https://accounts.googleapis.com/accounts/AuthSubSessionToken 

它看起來像我得到一個403錯誤。有任何想法嗎?

整個應用程序:

<?xml version="1.0" encoding="utf-8"?> 
<s:Application 
    xmlns:fx="http://ns.adobe.com/mxml/2009" 
    xmlns:s="library://ns.adobe.com/flex/spark" 
    xmlns:mx="library://ns.adobe.com/flex/mx" 
    minWidth="955" 
    minHeight="600" 
    initialize=" onInitialized() " 
    applicationComplete=" onLoaded() " 
    > 

    <fx:Script> 
     <![CDATA[ 

      import flash.external.ExternalInterface; 
      import flash.net.navigateToURL; 

      import mx.controls.Alert; 

      private function onInitialized() : void { 
       // Load the cross domain policy file for each of the googleapis.com 
       // domains used. At the very least, we need the ones for the API (photos) 
       // and the one for AuthSub for ActionScript (accounts). 
       Security.loadPolicyFile('http://photos.googleapis.com/data/crossdomain.xml'); 
       Security.loadPolicyFile('https://accounts.googleapis.com/crossdomain.xml'); 
      } 

      private function onLoaded() : void { 
       // Once the application has loaded, check to see if an AuthSub token was 
       // placed into the current page's URL. If it was, the user has already 
       // authenticated, we can continue to connect to the the service itself. 
       // In a real application, the long-term cookie would also be stored and 
       // checked here, to remove the need for the user to authenticate for this 
       // application every time it is used. 
       var searchPortion : String = ExternalInterface.call('window.location.search.toString'); 

       //searchPortion = "?token=tokenSavenFromPreviousAttempt"; 

       if (searchPortion.length > 0) { 
        // remove the ? from the token and extract the token. 
        searchPortion = searchPortion.substring(1); 

        // NOTE: Real applications should parse the URL properly. 
        if (searchPortion.indexOf('token=') == 0) { 

         log("token found: " + searchPortion); 

         getLongLivedToken(searchPortion.substring(6)); 
         return; 
        } 
       } 

       // No token found; redirect the user to the AuthSub page. Note that this URL 
       // is on the google.com domain. We can contact the google.com domain because 
       // this isn't a request from within Flash, but rather a page redirect. 
       var getTokenPage : URLRequest = new URLRequest('https://www.google.com/accounts/AuthSubRequest'); 

       // Construct the parameters of the AuthSub request. These are the same parameters 
       // as normal AuthSub, which can be found here: http://code.google.com/apis/accounts/docs/AuthSub.html#AuthSubRequest 
       var authSubParams : URLVariables = new URLVariables(); 
       authSubParams['scope'] = 'http://photos.googleapis.com/data'; // photos API 
       authSubParams['session'] = 1; // single-use token 
       authSubParams['secure'] = 0; // non-secure apps 
       authSubParams['next'] = 'http://localhost/AuthSub.html'; // The URL of this app. 
       //authSubParams['next'] = 'http://localhost/'; // The URL of this app. 

       log("token not found, sending AuthSubRequest"); 

       getTokenPage.data = authSubParams; 
       navigateToURL(getTokenPage, '_top'); 
      } 

      private function getLongLivedToken(singleUseToken : String) : void { 
       // Construct a call to the AuthSub for ActionScript endpoint on accounts.googleapis.com. 
       // This call will exchange the single use token given to use by AuthSub for a long-term 
       // token that we can use to make requests to endpoints such as Photos. 
       var getTokenRequest : URLRequest = new URLRequest('https://accounts.googleapis.com/accounts/AuthSubSessionToken'); 

       // Due to a bug in Flash, a URLRequest with a GET request will 
       // not properly send headers. We therefore use POST for this and *ALL* 
       // requests. 
       getTokenRequest.method = URLRequestMethod.POST; 

       // Due to a bug in Flash, a URLRequest without a valid parameter will 
       // not properly send headers. We therefore add a useless parameter to 
       // make this code work. 
       getTokenRequest.data = new URLVariables('pleaseignore=ignore'); 

       // Add the AuthSub for ActionScript headers. 
       getTokenRequest.requestHeaders.push(new URLRequestHeader('Authorization', 'AuthSub token="' + singleUseToken + '"')); 

       // Create the loader to get the token itself. The loader will callback 
       // to the following event handlers if and when the server responds. 
       var getToken : URLLoader = new URLLoader(); 
       getToken.addEventListener(Event.COMPLETE, onGetTokenResult); 
       getToken.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onGetTokenFailed); 
       getToken.addEventListener(IOErrorEvent.IO_ERROR, onGetTokenFailed); 
       getToken.addEventListener(HTTPStatusEvent.HTTP_STATUS, onHttpStatus); 

       log("getLongLivedToken: singleUseToken: " + singleUseToken); 

       try { 
        getToken.load(getTokenRequest); 
       } catch (e : Error) { 

        log("error:\n" + e.message); 

        Alert.show('Some error occurred: ' + e); 

       } 
      } 

      private function onGetTokenResult(e : Event) : void { 


       // Load the parameters from the response. 
       var getToken : URLLoader = URLLoader(e.target); 
       var params : URLVariables = new URLVariables(getToken.data); 


       // Parse the session token from the result. Real applications 
       // might at this point store the token in a long-term cookie so 
       // that repeated usages of the application do not require this entire 
       // authentication process. 
       var sessionToken : String = params.Token; 

       log("onGetTokenResult: sessionToken: " + sessionToken); 

       // Trim the newline from the end of the session token. 
       sessionToken = sessionToken.substring(0, sessionToken.length - 1); 

       Alert.show('session token: [' + sessionToken + ']'); 

       // Prepare a request to the photos API for the private album 
       // of the user. 
       var albumRequest : URLRequest = new URLRequest('http://photos.googleapis.com/data/feed/api/user/default'); 
       albumRequest.data = new URLVariables('access=private&amp;v=2&amp;err=xml'); 

       // Due to a bug in Flash, a URLRequest with a GET request will 
       // not properly send headers. We therefore use POST for this and *ALL* 
       // requests. 
       albumRequest.method = URLRequestMethod.POST; 

       var authsubHeader : String = 'AuthSub token="' + sessionToken + '"'; 

       // Add the Authorization header which uses the session token. 
       albumRequest.requestHeaders.push(new URLRequestHeader('Authorization', authsubHeader)); 

       // The X-HTTP-Method-Override header tells the Photos API to treat this request 
       // as a GET request, even though it is being conducted as a POST (due to the bug 
       // mentioned above). This is very important, as GData APIs will react differently 
       // to different HTTP request types. 
       albumRequest.requestHeaders.push(new URLRequestHeader('X-HTTP-Method-Override', 'GET')); 

       // We expect ATOM XML to be returned. 
       albumRequest.requestHeaders.push(new URLRequestHeader('Content-Type', 'application/atom+xml')); 

       var getAlbum : URLLoader = new URLLoader(); 
       getAlbum.addEventListener(Event.COMPLETE, onGetAlbumResult); 
       getAlbum.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onGetAlbumFailed); 
       getAlbum.addEventListener(IOErrorEvent.IO_ERROR, onGetAlbumFailed); 

       try { 
        getAlbum.load(albumRequest); 
       } catch (e : Error) { 
        Alert.show('Some error occurred: ' + e); 
       } 
      } 

      private function onGetAlbumResult(e : Event) : void { 
       // Load the XML from the response. 
       var getAlbum : URLLoader = URLLoader(e.target); 
       Alert.show('Returned XML: ' + getAlbum.data); 
      } 

      private function onGetTokenFailed(e : ErrorEvent) : void { 
       log("onGetTokenFailed: " + e.text); 
       Alert.show('Some error occurred: ' + e); 
      } 

      private function onGetAlbumFailed(e : ErrorEvent) : void { 
       log("onGetAlbumFailed: " + e.text); 
       Alert.show('Some error occurred: ' + e); 
      } 

      private function onHttpStatus(e : HTTPStatusEvent) : void { 
       log("onHttpStatus: " + e); 
       Alert.show('Some error occurred: ' + e); 
      } 

      private function log(message : String) : void 
      { 
       trace(message); 

       debugOutput.text = debugOutput.text ? debugOutput.text : ""; 

       debugOutput.text = debugOutput.text.length == 0 ? message : debugOutput.text + "\n" + message; 
      } 

     ]]> 
    </fx:Script> 

    <s:TextArea 
     id="debugOutput" 
     left="5" 
     right="5" 
     top="5" 
     bottom="5" 
     /> 

</s:Application> 

回答

0

變化:

var searchPortion : String = ExternalInterface.call('window.location.search.toString'); 

var searchPortion : String = decodeURIComponent(ExternalInterface.call('window.location.search.toString')); 
0

私有函數裝載的():無效{ //一旦應用程序加載,檢查查看AuthSub令牌是否被放置在當前頁面的URL中 。如果是,用戶已經認證了,我們可以繼續連接到服務本身。 //在實際的應用程序中,長期cookie也會被存儲,並且在這裏被選中,以消除用戶每次使用該應用程序時都需要認證這個 //應用程序。 var searchPortion:String = ExternalInterface.call('window.location.search.toString');

// searchPortion =「?token = tokenSavenFromPreviousAttempt」;

if(searchPortion.length> 0){ //刪除?從令牌中提取令牌。 searchPortion = searchPortion.substring(1);

//注意:真正的應用程序應該正確解析URL。 如果(searchPortion.indexOf( '標記=')== 0){

log("token found: " + searchPortion); 

    getLongLivedToken(searchPortion.substring(6)); 
    return; 

} }

令牌沒有被正確解析。使用 var token:String = Application.application.parameters [「token」];改爲 ;