OneDrive for Business Javascript访问NodeJS没有响应

时间:2014-10-10 10:13:58

标签: javascript sharepoint azure sharepoint-2013 onedrive

我有一个nodejs应用服务器试图访问我的组织onedrive上的文件。该应用程序已在Azure中注册,我可以进行图形api调用并获取结果。当我尝试调用onedrive api时它挂起而没有响应,api是:

https://-my.sharepoint.com/personal//_api/file

我使用的资源是“https://-my.sharepoint.com”。我也尝试过Microsoft.Sharepoint

我正在传递oauth令牌(在标题中):

  'Authorization': 'Bearer ' + aToken,
  'Accept': 'application/json;odata=minimalmetadata;charset=utf-8'

我还尝试在resoureid(http://office.microsoft.com/sharepoint/)中在Azure中为office 365 sharepoint在线添加URL,但这回来时没有为该帐户注册错误资源。


在chrome请求标头上使用REST工具,如下所示:

接受:application / json 授权:持票人eyJ0eXAiOiJKV1QiLCJhbGci ...... 连接:保持活力 Content-Type:application / xml 来源:chrome-extension:// rest-console-id 用户代理:Mozilla / 5.0(Macintosh; Intel Mac OS X 10_9_5)AppleWebKit / 537.36(KHTML,与Gecko一样)Chrome / 38.0.2125.104 Safari / 537.36

回复标题:

Status Code: 200
Date: Mon, 20 Oct 2014 18:53:55 GMT
Content-Encoding: gzip
Vary: Accept-Encoding
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Transfer-Encoding: chunked
P3P: CP="ALL IND DSP COR ADM CONo CUR CUSo IVAo IVDo PSA PSD TAI TELo OUR SAMo CNT COM INT NAV ONL PHY PRE PUR UNI"
X-SharePointHealthScore: 0
X-SP-SERVERSTATE: ReadOnly=0
request-id: 5611c49c-b0b2-1000-8ca2-5acda39588a3
MicrosoftSharePointTeamServices: 16.0.0.3312
X-MS-InvokeApp: 1; RequireReadOnly
Last-Modified: Mon, 20 Oct 2014 18:53:54 GMT
Server: Microsoft-IIS/7.5
SPRequestGuid: 5611c49c-b0b2-1000-8ca2-5acda39588a3
X-FRAME-OPTIONS: SAMEORIGIN
Content-Type: application/json;odata=minimalmetadata;streaming=true;charset=utf-8
Cache-Control: private, max-age=0
SPClientServiceRequestDuration: 1642
X-Content-Type-Options: nosniff
Expires: Sun, 05 Oct 2014 18:53:54 GMT

Request: 
Request Url: https://xxxx-my.sharepoint.com/personal/satish_ramjee_xxxxx_co_uk/_api/files
Request Method: GET
Status Code: 200
Params: {}
这将返回预期的JSON对象


相关代码如下

'use strict';

var express = require('express');
var request = require('request');
var http = require('http');
var path = require('path');
var passport = require('passport');
var AzureAdOAuth2Strategy = require('passport-azure-ad-oauth2');
var engine = require('ejs-locals');
var app = express();

var config = {
   // Enter the App ID URI of your application. To find this value in the Windows Azure Management Portal,
  // click Active Directory, click Integrated Apps, click your app, and click Configure.
  // The App ID URI is at the bottom of the page in the Single Sign-On section.
  realm: 'http://localhost:4000',

    
  // Enter the endpoint to which your app sends sign-on and sign-out requests when using WS-Federation protocol.
  // To find this value in the Windows Azure Management Portal, click Active Directory, click Integrated Apps,
  // and in the black menu bar at the bottom of the page, click View endpoints.
  // Then, copy the value of the WS-Federation Sign-On Endpoint.
  // Note: This field is ignored if you specify an identityMetadata url
  identityProviderUrl: 'https://login.windows.net/8b87af7d-8647-xxxxxxx/wsfed',

  // Enter the logout url of your application. The user will be redirected to this endpoint after
  // the auth token has been revoked by the WSFed endpoint.
  logoutUrl: 'http:/localhost:4000/',

  // Enter the URL of the federation metadata document for your app or the cert of the X.509 certificate found
  // in the X509Certificate tag of the RoleDescriptor with xsi:type="fed:SecurityTokenServiceType" in the federation metadata.
  // If you enter both fields, the metadata takes precedence
  identityMetadata: 'https://login.windows.net/8b87af7d-8647-4dc7-xxxxxxxx/federationmetadata/2007-06/federationmetadata.xml'
};


var graphConfig = {
// Enter the domain for your Active directory subscription, such as contoso.onmicrosoft.com
  tenant: '8b87af7d-8647-4dc7-xxxxxxxxxxxxxxx', 
  // Enter the Client ID GUID of your app.
  // In the Windows Azure Management Portal, click Active Directory, click your tenant,
  // click Integrated Apps, click your app, and click Configure.
  // The Client ID is on this app configuration page.
  clientid: '2462ee60-5695-xxxxxxxxxxxxxx',

  //Enter the value of the key for the app. You can create the key on the Configure page for the app.
  // The value appears only when you first save the key. Enter the saved value.
  clientsecret: 'xxxxxxxxxxxxxxxx'
};

// array to hold logged in users
var users = [];

// AAD Graph Client for AAD queries
var graphClient = null;
var aToken;

// use ejs-locals for all ejs templates:
app.engine('ejs', engine);

app.configure(function(){
  app.set('port', process.env.PORT || 4000);
  app.set('views',__dirname + '/views');
  app.set('view engine', 'ejs');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieParser('your secret here'));
  app.use(express.session({ secret: 'keyboard cat' }));
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));
});

app.configure('development', function(){
  app.use(express.errorHandler());
});

var findByEmail = function (email, fn) {
  for (var i = 0, len = users.length; i < len; i++) {
    var user = users[i];
    if (user.email === email) {
      return fn(null, user);
    }
  }
  return fn(null, null);
};


// Simple route middleware to ensure user is authenticated.
//   Use this route middleware on any resource that needs to be protected.  If
//   the request is authenticated (typically via a persistent login session),
//   the request will proceed.  Otherwise, the user will be redirected to the
//   login page.
var ensureAuthenticated = function(req, res, next) {
  if (req.isAuthenticated()) {
    return next();
  }
  res.redirect('/login');
};

//var RESOURCE = "https://graph.windows.net"; 
//var REST_CALL = 'https://graph.windows.net/' + graphConfig.tenant + '/Users()';
var RESOURCE = "https://xxxx-my.sharepoint.com";
var REST_CALL = "https://xxxx-my.sharepoint.com/personal/satish_ramjee_xxxxxx_co_uk/_api/files";

//passport.use(wsfedStrategy);
passport.use(new AzureAdOAuth2Strategy ({
    clientID: graphConfig.clientid,
    clientSecret: graphConfig.clientsecret,
    tenant: graphConfig.tenant,
    resource: RESOURCE,
    callbackURL: "http://localhost:4000/callback",
  },
  function(accessToken, refreshToken, params, profile, done) {
        console.log("access token ---> " + accessToken);
        aToken = accessToken;
        console.log("done ---> " + JSON.stringify(done));
    
        var waadProfile = profile || jwt.decode(params.id_token, '', true);
        console.log("waad ---> " + JSON.stringify(waadProfile));
    
//        _res.redirect("/ok");
//        User.findOrCreate({ id: waadProfile.upn }, function (err, user) {
          return done();
//        });
}));

var sp_files = function(callback) {
  var headers = {
      'Authorization': 'Bearer ' + aToken,
      'Accept': 'application/json',
  };

 if (RESOURCE.indexOf("graph") != -1) {
     headers[ 'x-ms-dirapi-data-contract-version'] = '0.5';
 }
    
    console.log("CALL___________________ "+REST_CALL);
  request({
    url: REST_CALL,
//    qs: qs, 
    headers: headers
  }, function(err, resp, body) {
     console.log("Body " + body);
      console.log("Err " + err);
//    if (err) return callback(err, null);
        
    if (resp && resp.statusCode != 200) {
      return callback(new Error(body), null);
    }
    else if (!resp) {
        return callback(null, null);
    }

//    { results: 
//   [ { __metadata: [Object],
//       Manager: [Object],
//       DirectReports: [Object],

    var d = JSON.parse(body).d,
      users = d.results;
//      meta = buildMetadata(d);
      console.log("users" + users);
      return callback(users);
  })
 
  console.log("Sent request---->");
}

http.createServer(app).listen(app.get('port'), function(){
  console.log("Express server listening on port " + app.get('port'));
});

var graphQuery = function(res, user) {
  graphClient.getUsers(function(err, result) {
    if(err) {
      res.end('GraphClient.getUsers error:' + err + '\n');
    } else {
    
        console.log("User " + JSON.stringify(result) );
        
      //res.render('index', { user: user, data: JSON.stringify(result) });
    }
    // get user properties (user.DisplayName, user.Mail, etc.)
  });
};

var doWaad = function(res, user) {
  if(graphClient === null) {
    waad.getGraphClientWithClientCredentials2(graphConfig.tenant, graphConfig.clientid, graphConfig.clientsecret, function(err, client) {
      if(err) {
        res.end('waad.getGraphClientWithClientCredentials2 error:' + err + '\n');
      } else {
        graphClient = client;
        graphQuery(res, user);
      }
    });
  } else {
    graphQuery(res, user);
  }
};

app.get('/cb', function(req, res) {
    console.log("cb");
});

app.get('/fail', function(req, res) {
    console.log("fail");
});
app.get('/ok', function(req, res) {
    console.log("*************** ok ", req.user);
    //doWaad(res, req.user);
});




app.get('/', function(req, res){
  if (aToken) {
      console.log("T: " + aToken);
      sp_files(function(d) {

        var mail = [];
          if (d)
          for (var i=0; i< d.length; i++) {
              console.log(i + ">>>>  " + d[i]);
//              if (d[i].Mail)
//              mail.push(d[i].Mail);
              if (d[i])
              mail.push(JSON.stringify(d[i]));
          }
          res.render('result', { user: d, data: mail, oauth: aToken});
      });
      
  } else {
    res.render('index', { user: null});
  }
});

app.get('/account', ensureAuthenticated, function(req, res){
  res.render('account', { user:req.user });
});



app.get('/login',
  passport.authenticate('azure_ad_oauth2', { 
    failureRedirect: '/fail'
  })
);



app.get('/callback', 
    passport.authenticate('azure_ad_oauth2', { failureRedirect: '/', failureFlash: true }),
    function(req, res) {
      // Successful authentication, redirect home.
    console.log("================= callback");
      res.redirect('/ok');
    }
);


app.get('/logout', function(req, res){

// clear the passport session cookies
  req.logout();

// We need to redirect the user to the WSFED logout endpoint so the
// auth token will be revoked
  wsfedStrategy.logout({}, function(err, url) {
    if(err) {
      res.redirect('/');
    } else {
      res.redirect(url);
    }
  });
});

// Passport session setup.
//   To support persistent login sessions, Passport needs to be able to
//   serialize users into and deserialize users out of the session.  Typically,
//   this will be as simple as storing the user ID when serializing, and finding
//   the user by ID when deserializing.
passport.serializeUser(function(user, done) {
  done(null, user.email);
});

passport.deserializeUser(function(id, done) {
  findByEmail(id, function (err, user) {
    done(err, user);
  });
});

这是主要的app.js节点代码,它与图形api一起使用,但不与sharepoint api一起使用。一旦收到令牌,就会调用函数sp_files来发出https请求。 sharepoint调用挂起时没有响应,虽然这是javascript但它仍然是服务器端,所以跨域问题在这里不应该相关。

1 个答案:

答案 0 :(得分:2)

确定问题,sharepoint正在IIS上运行,它不支持TLS,但支持SSLv3。 NodeJS通过defualt使用TLS,我将其更改为使用SSLv3,现在它可以正常工作。

然而,遗憾的是,最近发现SSLv3易受攻击并易受POODLE MITM攻击。