首页 > 关于Node.js前后端分离的一些疑问?

关于Node.js前后端分离的一些疑问?

最近公司准备把一个老项目的WEB端优化一下,打算用Nodejs做前端,这样可以和移动APP共用大部分的接口,减少后端的维护工作量。

本人小白一个,一直对前端也比较感兴趣,所以就负责这个项目的开发工作。
之前做了些功课,所以最后决定nodejs框架选择 express , 模板的话比较喜欢ejs ,前端框架就直接bootstrap + jquery

第一个问题就是想知道目录结构应该如何定义,我是按照express默认的目录结构设计的。想知道比较专业的目录结构应该是什么样的,或者是比较合理的。 下面我会把我的目录结构及文件内容及构成说一下,请大家帮忙指点一下

下面就对每个文件详细介绍了

以上就是我的目录就够和文件构成, 希望专家们能够帮我提提意见, 本人小白一个,看看我这个项目怎么改进,能够更好。谢谢了

第二个问题就是, 我的APP.JS 还请专家给看写的是否合理, 对于一个互联网的产品来说还需要哪些中间件或者需要安全上有哪些考虑

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

//加载配置文件
var settings = require('./config/settings');
//加载路由文件
var index = require('./routes/index');
var search = require('./routes/search');
var users = require('./routes/users');
var business = require('./routes/business');
var maps = require('./routes/maps');
var direct = require('./routes/direct');
var tourism = require('./routes/tourism');

var app = express();

//设置Express的模板文件类型、目录、后缀
app.set('views', path.join(__dirname, 'views'));
app.engine('.html', require('ejs').__express);
app.set('view engine', 'html');

//设置开发环境并记录日志
var logdir = path.join(__dirname, 'logs');
fs.existsSync(logdir) || fs.mkdirSync(logdir);
var alogstream = filestream.getStream({
    date_format: 'YYYYMMDD',
    filename: path.join(logdir, 'access-%DATE%.log'),
    frequency: 'daily',
    verbose: false
})
app.use(logger('combined', {stream: alogstream}));
//加载解析json中间件
app.use(bodyParser.json());
//加载解析urlencode中间件
app.use(bodyParser.urlencoded({ extended: false }));
//加载解析cookie中间件
app.use(cookieParser());
//加载静态文件目录设置
app.use(express.static(path.join(__dirname, 'public')));
//设置session
app.use(session({
    //用来对session数据进行加密的字符串.这个属性值为必须指定的属性。
    secret: settings.SESSION_SECRET, 
    //表示cookie的name,默认cookie的name是:connect.sid。
    //name: 'bjbus.com',
    //cookie过期时间,毫秒。
    //cookie: {maxAge: 60000},
    //指每次请求都重新设置session cookie,假设你的cookie是6000毫秒过期,每次请求都会再设置6000毫秒。
    resave: true,
    //是指每次请求都重新设置session cookie,假设你的cookie是6000毫秒过期,每次请求都会再设置6000毫秒。
    saveUninitialized: true,
}));

app.use(function(req, res, next){
    res.locals.title = settings.SITETITLE;
    res.locals.keywords = settings.SITEKEYWORDS;
    res.locals.description = settings.SITEDISCRIPTION;
    var _user = req.session.userinfo;
    if(_user){
        res.locals.userinfo = _user;
    }
    next();
});

//设置路由指向
app.use('/', index);
app.use('/search', search);
app.use('/users', users);
app.use('/business', business);
app.use('/direct', direct);
app.use('/maps', maps);
app.use('/direct', direct);
app.use('/tourism', tourism);


module.exports = app;

第三个问题就是我不知道如何在用户登录后session的页面判断上怎么能够写的更加简洁,以下是我目前的写法, 但是这个每个需要判断的session的地方都要这么些,感觉有点累

第四个问题是, 在登录的时候我是这么实现的, 用户在进入登录页后,我先生成一个uuid 这个uuid 我是通过IP + 随机数 + SESSION_SECRET 然后MD5加密出来的,然后将这个值放到session中 , 用户登录时,需要提交用户名,密码 和 uuid ,服务端去验证这个uuid是否和session中的一致,如果一样证明没问题,然后再判断用户信息是否正确。下面是代码

/* 登录页面 */
router.get('/login', function(req, res, next) {
    if(req.session.userinfo){
        res.render('error.html', { 
            errormsg: msg.is_login
        });
        return;
    }

    var uuid = functions.getClientIP(req) + functions.randomNum(false, 6) + settings.SESSION_SECRET;
    uuid = functions.dz_md5(uuid);
    req.session.uuid = uuid;
    res.locals.title = "用户登录 - " + res.locals.title;
    res.render('login.html', { 
        uuid: uuid
    });
    
});
/* 登录处理 */
router.post('/doLogin/:u/:p/:uuid/:r', function(req, res, next) {
    if(req.session.userinfo){
        res.json({ 
            errormsg: msg.is_login
        });
        return;
    }
    var u = req.params.u
    ,p = req.params.p
    ,uuid = req.params.uuid;
    if(uuid == req.session.uuid){
        if(functions.isEmpty(u) || functions.isEmpty(p)){
            res.json({errorMsg: msg.user_error}); 
        }else{
            var param = [];
            param.push("v_act=v_login")
            param.push("v_mid=" + settings.Interface.mid);
            param.push("v_pass=" + p);
            param.push("v_uname=" + u);
            functions.dz_http_get(param, function(data){
                if(typeof data === 'string'){
                    res.json({errorMsg: data}); 
                }else{
                    var userinfo = {
                        uid: data.uid,
                        uname: data.uname,
                        phone: data.phone
                    }
                    req.session.userinfo = userinfo;
                    req.session.uuid = null;
                    res.json(data); 
                }
            });
        }
        
    }else{
        res.json({errorMsg: msg.login_overtime}); 
    }
});

目前只是刚刚开始,后续的问题可能还有很多,还请大家多多帮助!有问题会继续更新,大家拜托了!

继续更新遇到的问题 --- 0718

先来让大家看看我的http.get是怎么写的

dz_http_get: function(param, callback){
        //param 是接口需要的参数
        param = param.join("&");
        param += "&v_sign=" + this.dz_md5(param+settings.Interface.key);
        var url = settings.Interface.url + param;
        logger.info(url);
        http.get(url, function(response) {
            if(response.statusCode == 200){
                var resJson = "";
                response.setEncoding('utf8');
                response.on('data', function(data){
                    resJson += data;
                });
                response.on('end', function () {
                    logger.debug(resJson);
                    resJson = JSON.parse(resJson);
                    if(resJson.v_status == "00"){
                        return callback(resJson.v_data)
                    }else{
                        return callback(resJson.v_scontent)
                    }
                });
            }else{
                return callback(msg.response_err)
            }
        }).on('error', function(e) {
            return callback(msg.request_err)
        });
},

目前我遇到了这么一个问题,我提交给服务端接口的URL 如果里面包含中文,则node.js的http.get 返回的就是400错误。如果中文encode就没事儿了, 包含中文的链接在浏览器中都是没问题的,只是在node中报错,还请大神看看这个是什么问题

http://xxxxxx?v_act=v_ecpeople&v_mid=10005&v_pic=10007510000000000001&v_pid=46272&v_pname=%E9%98%BF%E6%96%AF%E9%A1%BF&v_ptel=13800000001&v_tel=13671378601&v_type=1&v_uid=1&v_sign=a69bc72211cb8da82dc02467742fb80a

http://xxxxxx?v_act=v_ecpeople&v_mid=10005&v_pic=10007510000000000001&v_pid=46272&v_pname=阿斯顿&v_ptel=13800000001&v_tel=13671378601&v_type=1&v_uid=1&v_sign=a69bc72211cb8da82dc02467742fb80a

我赞同一楼的回答。

专门针对你关于验证用户session这一块来说,每次都写if(req.session.userInfo)当然不好,你可以做一个中间件,叫做sessioncheck,在appjs,就是你引入一大堆route的地方,放在需要登录的route前面,大概结构就是

app.use('/account', require('./routes/account'))

app.use(require('./checkSession'))
app.use('/api/user',require('./routes/api/user'))

我的这个项目里面,account里面包含了用户注册,登陆等页面,允许不通过sessionCheck就访问,后面的则需要通过,在sessionCheck那里失败了就会被强制跳转回account页面。这样子被sessionCheck保护了的route就不用考虑验证session了,拿来就用

以下是我的checkSession中间件,很简单

var checkSessionUser = function(req,res,next){
    //尝试获取session中的user,如果存在,说明已登录,直接使用
    if(req.session.user){
        next()
    }else{
        res.render('login')
    }
}

module.exports = checkSessionUser

是这样…
你这里nodejs做的应该算中间端。毕竟前端一般指你express里的views,nodejs以及express算后端更合适,只不过人家的nodejs及express通常访问的是数据库,而你访问的是另外一组api。

有一点是可以提醒一下的:你得花1个小时琢磨一下express中connect的机制,也就是中间件机制到底是怎么一回事。中间件就是帮助你处理大片api需要同样的前置或后置操作的情况的。

我们直接采用nodejs写的api操作数据库,前端用SPA,比你的方式更进一步。不过我们是从0开始,比较方便这样设计,具体情况得具体分析。


关于自己提的http.get的那个问题,也顺利解决了。主要是接口那边的问题,但是我也做了些修改
`
dz_http_get: function(param, callback){

    param.v_sign = this.dz_md5(decodeURIComponent(querystring.stringify(param)) + settings.Interface.key);
    var q = querystring.stringify(param).replace('%3A',':');
    logger.info(settings.Interface.url + q);
    http.get(settings.Interface.url + q, function(response) {
        if(response.statusCode == 200){
            var resJson = "";
            response.setEncoding('utf8');
            response.on('data', function(data){
                resJson += data;
            });
            response.on('end', function () {
                logger.debug(resJson);
                resJson = JSON.parse(resJson);
                if(resJson.v_status == "00"){
                    return callback(resJson.v_data)
                }else{
                    return callback(resJson.v_scontent)
                }
            });
        }else{
            return callback(msg.response_err)
        }
    }).on('error', function(e) {
        return callback(msg.request_err)
    });
},

`
还请大家在看看这么些有什么问题没有,还有就是http.get这个可以优化吗,就是希望获取后台接口可以再提速

【热门文章】
【热门文章】