Dropzone,Angular 2使用passportjs验证上传

时间:2017-04-18 02:44:22

标签: javascript angular typescript passport.js dropzone.js

我使用带护照的Express和带有mysql的护照本地策略来验证特定页面的管理员用户。哪个有效,在带有Angular 2应用程序的管理页面中,我有一个Dropzone和另一个表单,每个表单都提交给两个不同的URL。我不确定如何在上传时验证用户是否已登录。

这是服务器代码:

const express       = require('express');
const path          = require('path');
const fs            = require('fs');
const I             = require('./server/image');
const marked        = require('marked');

const session       = require('express-session');
const cookieParser  = require('cookie-parser');
const bodyParser    = require('body-parser');
const passport      = require('passport');
const flash         = require('connect-flash');
const formidable    = require('formidable');

const mysql         = require('mysql');
const LocalStrategy = require('passport-local').Strategy;

// const valid         = require('express-validator');

isLoggedIn = (req, res, next) => {

    if (req.isAuthenticated()){
        console.log("logged in");
        return next();
    }

    console.log("not logged in");
    res.redirect('/');
};

var connection = mysql.createConnection({
    'host': 'localhost',
    'user': 'localhost',
    'password': 'localhost'
});

connection.query('USE passport');

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

passport.deserializeUser(function(id, done) {
    connection.query("SELECT * FROM users WHERE id = ? ", [id], function(err, rows) {
        done(err, rows[0]);
    });
});

passport.use('local-login', new LocalStrategy({
    // by default, local strategy uses username and password, we will override with email
    usernameField: 'username',
    passwordField: 'password',
    passReqToCallback: true // allows us to pass back the entire request to the callback
}, function(req, username, password, done) { // callback with email and password from our form
    connection.query("SELECT * FROM users WHERE username = ?", [username], function(err, rows) {
        if (err)
            return done(err);
        if (!rows.length) {
            return done(null, false, req.flash('loginMessage', 'No user found.')); // req.flash is the way to set flashdata using connect-flash
        }

        // if the user is found but the password is wrong
        // if (!bcrypt.compareSync(password, rows[0].password))
          if(password != rows[0].password)
            return done(null, false, req.flash('loginMessage', 'Oops! Wrong password.')); // create the loginMessage and save it to session as flashdata

        // all is well, return successful user
        return done(null, rows[0]);
    });
}));

var image = new I();

var app = express();

app.use(cookieParser());
app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(bodyParser.json());
app.use(session({
  secret: 'testingsecret',
  resave: true,
  saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());

app.use('/', express.static(path.join(__dirname, 'front-end/dist')));
app.use('/admin', isLoggedIn, express.static(path.join(__dirname, 'admin/dist')))

app.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', 'http://localhost:4200');
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Cache-Control');
    next();
});

app.use("/bc", express.static(path.join(__dirname, "bower_components")));
app.use("/i", express.static(path.join(__dirname, "image")));

app.get('/admin', isLoggedIn, (req, res) => {
    res.sendFile(path.join(__dirname, 'admin/dist/index.html'));
});

app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'front-end/dist/index.html'));
});


app.get('/login', (req, res) => {
    res.sendFile(path.join(__dirname, 'login.html'));
});

app.post('/login', passport.authenticate('local-login', {
    successRedirect: '/admin',
    failureRedirect: '/login',
    failureFlash: true
}), (req, res) => {
    if (req.body.remember) {
        req.session.cookie.maxAge = 1000 * 60 * 3;
    } else {
        req.session.cookie.expires = false;
    }
    res.redirect('/');
});

app.get('/logout', (req, res) => {
    req.logout();
    res.redirect('/');
});

findUnique = (file, pth) => {
    var post = file.match(/.\w+$/)[0];
    var pre = file.replace(post, '');
    pre = pre +"(";
    post = ")"+post;
    for(var i=1; i<5000; i++){
        if(!fs.existsSync(path.join(pth, pre+i+post))){
            return pre+i+post;
        }
    }
};

app.post('/upload-image', isLoggedIn, (req, res) => {
    var form = formidable.IncomingForm();
    form.uploadDir = path.join(__dirname, "image");

    var fileIn;

    form.parse(req, (err, fields, files) => {
        fileIn = files;
    });

    form.on('end', () => {
        var name = fileIn.file.name;
        var pth = fileIn.file.path;
        var pthNew = path.dirname(pth);
        if(fs.existsSync(path.join(pthNew, name))){
            name = findUnique(name, pthNew);
        }
        fs.rename(pth, path.join(pthNew, name));
        res.send({filename: name});
    });

});

app.listen(8080);

我认为我需要做的是获取具有会话ID或cookie的标头信息,并通过在其中设置标头将其与Dropzone中的上传一起发送。但我不知道该怎么做。

客户端Angular 2:

import { Component, AfterContentInit } from '@angular/core';
import { Http, Headers, RequestOptions } from '@angular/http';
import { ImageService } from './image.service';

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

declare var Dropzone: any;

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements AfterContentInit {

    constructor(private image: ImageService, private http: Http) {}

    ngAfterContentInit(): void {
        this.dropzone = new Dropzone('form#dropzone', {
            url: "http://localhost:8080/upload-image",
            parallelUploads: 5,
            autoProccessQueue: true,
            acceptedFiles: "image/*"
        });

        this.dropzone.on('success', (file, res) => {
             console.log(res.filename);
        });
    }
}

1 个答案:

答案 0 :(得分:0)

我找到了答案here。基本上我需要包括为护照生成的cookie。这是通过启用withCredentials

来完成的

悬浮窗

this.dropzone = new Dropzone('form#dropzone', {
            url: "http://localhost:8080/upload-image",
            parallelUploads: 5,
            autoProccessQueue: true,
            acceptedFiles: "image/*",
            withCredentials: true  //    <<-----
        });

Angular 2

let head = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions({ headers: head, method: "post", withCredentials: true});

withCredentials设置为true可以对单独的请求进行身份验证。