2016-02-12 58 views
1

我做了教程,使用IoT Foundation Service和.js樣板可視化我的樹莓派中的數據。Bluemix Single Sign On不顯示登錄頁面

我也跟着下面的教程:

https://developer.ibm.com/recipes/tutorials/visualizing-your-data/

,一切工作正常。

現在我嘗試添加單點登錄服務進行身份驗證。我創建了一個雲註冊表並添加了兩個測試用戶。之後,我將服務綁定到我的物聯網可視化.js應用程序,並執行將我的應用程序與服務集成的步驟。我跟着官方文檔步驟執行這一(點「配置的Node.js應用程序」):

http://www.ng.bluemix.net/docs/services/SingleSignOn/configure_apps.html#tsk_configuringnodejsapp_express4

我修改了我的電腦上的文件和使用CL CLI上載他們。問題是,它沒有改變任何東西。我可以像以前一樣訪問我的應用程序,但沒有看到任何登錄頁面。

這裏是我的文件:

的package.json

{ 
    "name": "iot-visualization", 
    "version": "0.1.0", 
    "private": true, 
    "scripts": { 
    "start": "node app.js" 
    }, 
    "dependencies": { 
    "passport": "*", 
    "cookie-parser": "*", 
    "express-session": "*", 
    "passport-idaas-openidconnect": "*", 
    "express": "~4.2.0", 
    "serve-favicon": "~2.1.0", 
    "morgan": "~1.0.0", 
    "cookie-parser": "~1.0.1", 
    "body-parser": "~1.0.0", 
    "debug": "~0.7.4", 
    "jade": "~1.3.0", 
    "stylus": "0.42.3", 
    "express-session": "^1.8.1" 
    } 
} 

app.js(URL修改)

/******************************************************************************* 
* Copyright (c) 2014 IBM Corporation and other Contributors. 
* 
* All rights reserved. This program and the accompanying materials 
* are made available under the terms of the Eclipse Public License v1.0 
* which accompanies this distribution, and is available at 
* http://www.eclipse.org/legal/epl-v10.html 
* 
* Contributors: 
* IBM - Initial Contribution 
*******************************************************************************/ 

var express = require('express'); 
var path = require('path'); 
var favicon = require('serve-favicon'); 
var logger = require('morgan'); 
var cookieParser = require('cookie-parser'); 
var bodyParser = require('body-parser'); 
var session = require('express-session'); 


var index = require('./routes/index'); 

var app = express(); 

var http_host = (process.env.VCAP_APP_HOST || '0.0.0.0'); 
var http_port = (process.env.VCAP_APP_PORT || 7000); 

app.set('port', http_port); 
app.set('host',http_host); 

// view engine setup 
app.set('views', path.join(__dirname, 'views')); 
app.set('view engine', 'jade'); 
//use favicon 
app.use(favicon(__dirname + '/public/images/favicon.ico')); 
app.use(logger('dev')); 
app.use(bodyParser.json()); 
app.use(bodyParser.urlencoded()); 
app.use(cookieParser()); 
// add session to store the api-key and auth token in the session 
app.use(session({secret: 'xxxxxxxxxx',saveUninitialized: true, 
       resave: true})); 
app.use(require('stylus').middleware(path.join(__dirname, 'public'))); 

var passport = require('passport'); 
var cookieParser = require('cookie-parser'); 
var session = require('express-session'); 

app.use(cookieParser()); 
app.use(session({resave: 'true', saveUninitialized: 'true' , secret: 'keyboard cat'})); 
app.use(passport.initialize()); 
app.use(passport.session()); 

passport.serializeUser(function(user, done) { 
    done(null, user); 
}); 

passport.deserializeUser(function(obj, done) { 
    done(null, obj); 
});   

// VCAP_SERVICES contains all the credentials of services bound to 
// this application. For details of its content, please refer to 
// the document or sample of each service. 
var services = JSON.parse(process.env.VCAP_SERVICES || "{}"); 
var ssoConfig = services.SingleSignOn[0]; 
var client_id = ssoConfig.credentials.clientId; 
var client_secret = ssoConfig.credentials.secret; 
var authorization_url = ssoConfig.credentials.authorizationEndpointUrl; 
var token_url = ssoConfig.credentials.tokenEndpointUrl; 
var issuer_id = ssoConfig.credentials.issuerIdentifier; 
var callback_url = 'https://xxxxx.mybluemix.net/auth/sso/callback';   

var OpenIDConnectStrategy = require('passport-idaas-openidconnect').IDaaSOIDCStrategy; 
var Strategy = new OpenIDConnectStrategy({ 
       authorizationURL : authorization_url, 
       tokenURL : token_url, 
       clientID : client_id, 
       scope: 'openid', 
       response_type: 'code', 
       clientSecret : client_secret, 
       callbackURL : callback_url, 
       skipUserProfile: true, 
       issuer: issuer_id}, 
    function(iss, sub, profile, accessToken, refreshToken, params, done) { 
       process.nextTick(function() { 
     profile.accessToken = accessToken; 
     profile.refreshToken = refreshToken; 
     done(null, profile); 
      }) 
}); 

passport.use(Strategy); 
app.get('/login', passport.authenticate('openidconnect', {})); 

function ensureAuthenticated(req, res, next) { 
    if(!req.isAuthenticated()) { 
       req.session.originalUrl = req.originalUrl; 
     res.redirect('/login'); 
    } else { 
     return next(); 
    } 
} 

app.get('/auth/sso/callback',function(req,res,next) {    
      var redirect_url = req.session.originalUrl;     
      passport.authenticate('openidconnect', { 
        successRedirect: redirect_url,         
        failureRedirect: '/failure',       
      })(req,res,next); 
     }); 

app.get('/failure', function(req, res) { 
      res.send('login failed'); }); 

app.use(express.static(path.join(__dirname, 'public'))); 


app.use('/',index); 

app.use(function(req, res, next) { 
    if(req.session.api_key) 
    res.redirect("/dashboard"); 
    else 
    res.redirect('/login'); 
}); 

/// error handlers 

// development error handler 
// will print stacktrace 
if (app.get('env') === 'development') { 
    app.use(function(err, req, res, next) { 
     res.status(err.status || 500); 
     res.render('error', { 
      message: err.message, 
      error: err 
     }); 
    }); 
} 

// production error handler 
// no stacktraces leaked to user 
app.use(function(err, req, res, next) { 
    res.status(err.status || 500); 
    res.render('error', { 
     message: err.message, 
     error: {} 
    }); 
}); 

var server = app.listen(app.get('port'), app.get('host'), function() { 
    console.log('Express server listening on ' + server.address().address + ':' + server.address().port); 
}); 

module.exports = app; 

任何想法?

//編輯

有沒有.cfignore文件時,我第一次開始教程。所以,我創建了一個在我的應用程序的根文件夾下面的內容:

node_modules/passport 
node_modules/cookie-parser 
node_modules/express-session 
node_modules/passport-idaas-openidconnect 

這是正確的,爲什麼我沒有與本教程內容之前有這樣的文件:

node_modules 
+0

我認爲您的問題可能與Bluemix維護在構建之間保留的緩存目錄有關。此緩存用於存儲解析的依賴關係,因此不必在每次部署時都下載並安裝它們。您可能需要覆蓋此設置,並通過將NODE_MODULES_CACHE設置爲false來禁用它,以便部署更新的依賴項。我已經要求我的同事審查您的帖子並進一步發表評論。 – ValerieLampkin

+0

@ValerieLampkin雖然它確實使用緩存,但Bluemix將始終使用新的package.json運行'npm install'。 NPM識別出緩存缺少新添加的模塊並將安裝它。無論如何,如果模塊不在那裏,應用程序會崩潰,說模塊不存在。 –

+0

好吧,所以我不需要將NODE_MODULES_CACHE設置爲false?我還編輯了關於.cfignore文件的第一篇文章。 – Jenkins

回答

6

首先我假設變量callback_url的值是「xxxxx.mybluemix.net/auth/sso/回調「爲例。如果不是,則應該用您的應用程序名稱替換「xxxxx」。

正如Single Sign On - Configuring a Node.js app文檔報道:

的護照IDAAS-openidconnect模塊與護照版本0.1.1高達0.3.2。晚於0.3.2的版本可能無法正常工作。

我會確保您使用正確的護照版本(例如)在您的包中使用此行。JSON

"passport": "^0.2.2", 

如果你願意,你可以簡化你的回調函數,用於測試目的,這樣(沒有找到req.session.originalUrl它可能會引發錯誤),並在以後進行擴展:

app.get('/auth/sso/callback',function(req,res,next) {    
    passport.authenticate('openidconnect', { 
             successRedirect: "/home",        
             failureRedirect: '/failure',       
             } 
        )(req,res,next); 
}); 

的其餘代碼對我來說似乎還可以,因爲已經建議您必須將「ensureAuthenticated」函數鏈接到要在身份驗證下放置的每個app.get,app.post等。

例如嘗試做這樣的事情:

app.get('/home', ensureAuthenticated, function(req, res) { 
    var htmlSplashPage = "<!DOCTYPE html> <html> <body> <h1>Hello "+JSON.stringify(req.session.passport.user._json.displayName)+"</h1></body> </html>"; 
    res.writeHead(200, {'Content-Type': 'text/html','Content-Length':htmlSplashPage.length}); 
    res.write(htmlSplashPage); 
    res.end(); 
}); 

這麼做其實就是調用/家時,你得到的功能ensureAuthenticated之前所有的休息調用,並且僅當用戶已經通過身份驗證的下一個函數(家)被執行,否則你將被重定向到登錄頁面。

+0

我更改了package.json中的護照版本。我也改變了你的回調函數(而不是/我寫的/儀表板)。這也沒有使登錄彈出。我試圖把你的ensureAuthenticated放在app.get函數中,但實際上我不知道它在哪。因爲我只看到登錄,回調和失敗的功能,他們不需要這個檢查的權利?我唯一的頁面是/儀表板,但它是通過res.redirect(「/ dashboard」)調用的。 – Jenkins

+0

您需要將ensureAuthenticated鏈接到需要用戶身份驗證檢查的所有功能。 嘗試創建一個虛擬的app.get('/ test',ensureAuthenticated,function(req,res){[...]});並從瀏覽器中調用它來查看是否執行了ensureAuthenticated。它應該以下列方式工作: 1.您調用GET 2.首先確保已驗證已執行,並且應驗證條件!req.isAuthenticated()。爲此,它將重定向到登錄頁面 –

+0

我把這個函數放在我的代碼中'app.get('/ test',ensureAuthenticated,function(req,res){res.send('Hello World!'); });'。當我通過/測試呼叫我的Url時,我立即重定向到/儀表板頁面。我也找不到任何跡象表明該函數在我的日誌中執行(但正如你所說的,如果它被執行,則應該調用登錄頁面)。 – Jenkins

2

您需要將ensureAuthenticated函數添加到您的高速中間件堆棧中。每當向您的應用程序發出請求時,都需要調用該函數。例如,你可以把它添加到去你的應用程序中加入這一切要求:

app.use(ensureAuthenticated); 
+0

我在原始代碼的最後4行之前添加了這個。但它不起作用。我做錯了嗎? – Jenkins

+0

我仍然有這個問題。 – Jenkins