从源“null”访问 Twitter_OAuth_Url(从“http://localhost:3000/api/twitter-login”重定向)的 XMLHttpRequest 已被阻止
Posted
技术标签:
【中文标题】从源“null”访问 Twitter_OAuth_Url(从“http://localhost:3000/api/twitter-login”重定向)的 XMLHttpRequest 已被阻止【英文标题】:Access to XMLHttpRequest at Twitter_OAuth_Url ( redirected from 'http://localhost:3000/api/twitter-login') from origin 'null' has been blocked 【发布时间】:2019-11-24 13:10:02 【问题描述】:我在我的 MEAN STACK 应用程序中使用 passport-twitter。 我有一个端点 twitter-login,当 Angular 应用程序达到这一点时,passport-twitter 模块用于对用户进行身份验证。 在获取 oaut_token 时,它会将用户重定向到此 url:https://api.twitter.com/oauth/authenticate?oauth_token=SOME_TOKEN 在重定向时,应用程序在标题中抛出上述错误。 使用 cors 模块 或手动设置标题无济于事。
这是我的代码:app.ts
import express from 'express';
import mongoose from 'mongoose';
import bodyParser from 'body-parser';
import DATABASE_URL, JWTSECRET from './config/config';
import Routes from './routes/routes';
const passport = require('passport');
const cors = require('cors');
const cookieSession = require('cookie-session');
const cookieParser = require('cookie-parser');
const passportSetup = require('./config/passport-config');
class App
public app : express.Application;
public routePrv: Routes = new Routes();
constructor()
this.app = express();
this.config();
this.mongoSetup();
this.routePrv.routes(this.app);
private config(): void
this.app.use( cors() );
this.app.use( cookieSession(
name: "VIP_Session",
keys: [JWTSECRET],
maxAge: 24 * 60 * 60 * 100
)
);
this.app.use(cookieParser());
this.app.use(bodyParser.json());
this.app.use(bodyParser.urlencoded( extended: false ));
this.app.use(passport.initialize());
this.app.use(passport.session());
private mongoSetup(): void
mongoose.connect(DATABASE_URL, useCreateIndex: true, useNewUrlParser: true);
const connection = mongoose.connection;
connection.once('open', () =>
console.log('MongoDB connection established successfullly.');
);
export default new App().app;
server.ts
import app from './app';
import * as http from 'http';
import PORT from './config/config';
http.createServer(app).listen(PORT , () =>
console.log('Express server listening on port '+ PORT);
);
routes.ts
import Request, Response, NextFunction from "express";
const passport = require('passport');
export class Routes
public routes(app: any): void
app.route('/api/twitter-login').get(passport.authenticate('twitter'));
app.route('/api/twitter-callback').get(
passport.authenticate('twitter',
failureRedirect: 'http://localhost:4200/login?isAuthenticated=false',
successRedirect : 'http://localhost:4200/login?isAuthenticated=true'
));
passport-config.ts
const TwitterStrategy = require('passport-twitter');
import * as mongoose from 'mongoose';
import passport from 'passport';
import TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET from '../config/config';
import userSchema from '../models/';
let User = mongoose.model('User' , userSchema);
passport.serializeUser((user : any, done) =>
done(null, user._id);
);
// deserialize the cookieUserId to user in the database
passport.deserializeUser((id, done) =>
User.findById(id)
.then(user =>
done(null, user);
)
.catch(e =>
done(new Error("Failed to deserialize an user"));
);
);
passport.use('twitter', new TwitterStrategy(
consumerKey: TWITTER_CONSUMER_KEY,
consumerSecret: TWITTER_CONSUMER_SECRET,
includeEmail: true,
callbackURL: '/api/twitter-callback'
,
async (token : any, tokenSecret : any, profile : any, done : any) =>
console.log(profile.emails);
// find current user in UserModel
const currentUser = await User.findOne(
user_name: profile.username
);
// create new user if the database doesn't have this user
if (!currentUser)
const newUser = await new User(
first_name : profile.displayName.split(' ')[0],
last_name : profile.displayName.split(' ')[1],
user_name : profile.username,
email : profile.emails[0].value ,
avatar : profile.photos[0].value ? profile.photos[0].value : '',
twitterId : profile.id
).save();
if (newUser)
done(null, newUser);
done(null, currentUser);
));
【问题讨论】:
这是一个网络问题。 Twitter 正试图通过网络回调本地主机。究竟如何路由?将其放在云实例上并在其上放置一个域,然后让 twitter 回调到那里。您可以输入您的公共 IP 地址并查看它是否有效。 我确定的一件事是它的 cors 问题。如果我直接在 localhost:3000/api/twitter-login 之类的浏览器中达到此端点(而不是在我的场景中来自 Angular 应用程序)。 效果很好。仅当 Angular 应用程序到达此端点并且服务器脚本将其重定向到上述 twitter oauth url 时,它才会引发错误,请求标头中的源标头为空。 【参考方案1】:在做了一些研究后,我发现来自 Angular7 应用程序 的 api 调用应该使用以下方法之一。使用锚标记:@987654322 @或者window.location.href = 'http://SERVER_URL/api/twitter-login'
。
使用这种方法,origin 不会为空,passport-twitter 的所有回调都可以正常工作。
【讨论】:
这会将我重定向到用户身份验证 twitter 页面,但是当它重定向失败时以上是关于从源“null”访问 Twitter_OAuth_Url(从“http://localhost:3000/api/twitter-login”重定向)的 XMLHttpRequest 已被阻止的主要内容,如果未能解决你的问题,请参考以下文章
从源“null”访问“http://github/..file.json”处的 XMLHttpRequest 已被 CORS 策略阻止:
尝试使用导入的 js 函数启动 html 页面时出现“CORS 策略已阻止从源‘null’访问脚本”错误
从源“null”访问 Twitter_OAuth_Url(从“http://localhost:3000/api/twitter-login”重定向)的 XMLHttpRequest 已被阻止
从本地 html 文件到服务器的 JSON 请求引发 CORS 错误:CORS 策略已阻止从源“null”访问 <URL> 处的 XMLHttpRequest