簡體   English   中英

Angularjs CORS遇到Node,Express,Oauth2和Passport的麻煩

[英]Angularjs CORS trouble with Node, Express, Oauth2, and Passport

最近,我們決定將前端從EJS切換到Angular,將前端和后端完全分開。 為此,我們開始在多個瀏覽器中遇到多個問題。 在后端,我們使用帶有express的Node以及護照和oauth2。 對於前端,我們嘗試使用angular。 EJS使用express.render進行工作,但我們希望直接將express作為RESTful API來直接使用angular。

我分別在本地主機:8080和本地主機:3000上運行后端和前端。 當僅使用后端(使用EJS,不是ANGULAR)時,我可以成功地進入瀏覽器中的后端端口,通過Passport-oauth登錄,然后重定向到帳戶頁面(從提供商登錄屏幕),其中存放我的json數據通過res.json呈現。 問題是刪除EJS之后,我無法從前端UI進行此操作。

我嘗試過使用三種不同的瀏覽器,但運氣不好,以多種方式配置了CORS。 以下三個代碼段是我嘗試通過$ http和$ resource從前端訪問localhost:8080時在瀏覽器控制台中遇到的錯誤(請參見下面的代碼)。 嘗試從每個不同的瀏覽器訪問端口8080時,節點控制台告訴我這三個代碼段下方的圖像...

鉻:

XMLHttpRequest cannot load 'PROVIDER-DETAILS-URL'. No 'Access-Control-Allow-    Origin' header is present on the requested resource. Origin 'null' is therefore     not allowed access.

火狐:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at 'PROVIDER-DETAILS-URL'. (Reason: CORS header 'Access-Control-Allow-Origin' missing).
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at 'PROVIDER-DETAILS-URL'. (Reason: CORS request failed).

蘋果瀏覽器:

XMLHttpRequest cannot load http://localhost:8080/auth/PROVIDER. Request header field Accept-Encoding is not allowed by Access-Control-Allow-Headers.

控制台映像: 在此處輸入圖片說明

和代碼:

服務器:

app.js

'use strict';

const express           = require('express');
const session           = require('express-session');
const cookieParser      = require('cookie-parser');
const bodyParser        = require('body-parser');
const logger            = require('morgan');
const errorHandler      = require('errorhandler');
const path              = require('path');
const flash             = require('connect-flash');
const passport          = require('passport');
const expressValidator  = require('express-validator');

/**
 * Load environment variables, where API keys and passwords are configured.
 */
const config = require('./config/config');

/**
 * Route Handlers
 */
const index   = require('./routes/index');
const account = require('./routes/account');
const logout  = require('./routes/logout');

/**
 * API keys and Passport configuration.
 */
const passportConfig = require('./strategy');

/**
 * Create Express server.
 */
const app = express();

/**
 * Express configuration.
 */
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
    res.header("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT");
    next();
});
app.use(cookieParser());
app.use(expressValidator());
app.use(session({
    resave              : true,
    saveUninitialized   : true,
    secret              : config.sessionSecret,
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());

/**
 * Primary app routes.
 */
app.get('/', index.execute);
app.get('/account', passportConfig.isAuthenticated, account);
app.get('/logout', logout.execute);

/**
 * OAuth authorization routes.
 */
app.get('/auth/PROVIDER', passport.authenticate('PROVIDER'));
app.get('/auth/PROVIDER/callback', passport.authenticate('PROVIDER', { failureRedirect : '/'}), function(req, res) {
    res.redirect('/account');
});

/**
 * Error Handler.
 */
app.use(errorHandler());

/**
 * Start Express server.
 */
app.listen(8080, () => {
    console.log('App listening on port 8080');
});

module.exports = app;

strategy.js

'use strict';

const passport        = require('passport');
const session         = require('express-session');
const config          = require('./config/config');
const OAuth2Strategy  = require('passport-oauth').OAuth2Strategy;

/**
 * Put together the right header info for PROVIDER
 */
 var authString      = new Buffer(config.PROVIDER.clientID + ':' + config.PROVIDER.clientSecret);
 var customHeader    = {
    "Authorization": "Basic " + authString.toString('base64')
};

/**
 * OAuth2Strategy containing the customHeader created above.
 */
 passport.use('PROVIDER', new OAuth2Strategy({
    authorizationURL    : config.PROVIDER.authorizationURL,
    tokenURL            : config.PROVIDER.tokenURL,
    clientID            : config.PROVIDER.clientID,
    clientSecret        : config.PROVIDER.clientSecret,
    callbackURL         : config.PROVIDER.callbackURL,
    customHeaders       : customHeader,
    passReqToCallback   : true
},
function( req, accessToken, refreshToken, profile, done ) {
    req.session.accessToken = accessToken;
    return done(null, profile); 
}
));

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

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

/**
 * Login Required middleware.
 */
 exports.isAuthenticated = function(req, res, next) {
    if (req.isAuthenticated()) {
        console.log('isAuthenticated');
        return next();
    }
    res.redirect('/');
};

/**
 * Authorization Required middleware.
 */
 exports.isAuthorized = function(req, res, next) {
    var provider = req.path.split('/').slice(-1)[0];
    if (_.find(req.user.tokens, { kind: provider })) {
        next();
    } else {
        res.redirect('/auth/' + provider);
    }
};

index.js

exports.execute = function (req, res) {
    if (req.user) {
        console.log('========== ROUTES/INDEX.JS | 3 ==========');
        res.redirect('/account');
    } else {
        console.log('========== ROUTES/INDEX.JS | 6 ==========');
        res.redirect('/auth/PROVIDER');
    }
};

客戶:

我將其結合起來使其更易於閱讀。

angular.module('StackOverflowPost', [])

.factory('APIService', function() {
    function getData( $q, $http ) {
        var defer = $q.defer();
        $http.get( 'localhost:8080' )
            .success( getDataComplete )
            .catch( getDataFailed );

        function getDataComplete( response ) {
            console.log( response.Authorization );
            defer.resolve(response.data.results );
        }

        function getDataFailed( error ) {
            console.log( error.data );
            defer.reject( 'XHR Failed for getData - ' + error.data );
        }
        return defer.promise;
    }
})

.controller('MainCtrl', function( APIService ) {
    var vm = this;

    vm.getDataTest = function() {
        APIService.getData().then(function( returnedData ) {
            console.log( returnedData );
        })
    }
});

任何幫助或指示將不勝感激。

更新 (4/28/2016) :我更新了原始帖子,並提供了更多詳細信息。 經過一周的反復試驗,我還將代碼更新為現在的代碼。

請檢查一下

https://gist.github.com/dirkk0/5967221

代碼應該是

// in AngularJS (client)

myApp.config(['$httpProvider', function($httpProvider) {

    $httpProvider.defaults.useXDomain = true;
    delete $httpProvider.defaults.headers.common['X-Requested-With'];
}]);

// in Express/nodeJS

// in NodeJS/Express (server)
app.all('/*', function(req, res, next) {
   res.header("Access-Control-Allow-Origin", "*");
   res.header("Access-Control-Allow-Headers", "X-Requested-With");
   res.header("Access-Control-Allow-Methods", "GET, POST","PUT");
   next();

});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM