实现前后端登录注册界面

本篇博客讲解如何实现前后端的简单登录注册界面,后端代码由node.js实现,主要阐述登录注册时网页工作原理。感兴趣的同学可以参考一下。

注册界面

功能:

  • 判断用户是否输入邮箱,密码,验证密码(前端判断)
  • 判断用户的邮箱格式是否正确(后端判断)
  • 判断输入的密码和验证密码是否一致(前端判断)
  • 判断注册的邮箱是否唯一(后端判断)

1.html部分:

<div class="form-wrapper">
    <h1>注册</h1>
    <form id="RegisterForm" >
        <div class="row">
            <lable>邮箱</lable>
            <input type="text" name="email">
            <span class="error"></span>
        </div>
        <div class="row">
            <lable>密码</lable>
            <input type="password" name="password">
            <span class="error"></span>
        </div>
          <div class="row">
              <lable>确认密码</lable>
              <input type="password" name="password_confirm">
              <span class="error"></span>
          </div>
            <div class="row">
                <input type="submit">
            </div>

    </form>
</div>

2.js部分(由jquery实现):

监听表单的submit事件,将用户输入的信息存储到hash表中,如果用户输入不合法则出现错误提示信息

$('#RegisterForm').on('submit',(e) => {
    e.preventDefault();
    let hash = {};
    let arg = ['email','password','password_confirm'];
    arg.forEach((name) => {
        let value = $('#RegisterForm').find(`[name= ${name}]`).val();
        hash[name] = value;
    })
    $('#RegisterForm').find('.error').each((index,span) => {
        $(span).text(''); //初始的错误提示为空
    })
    if(hash['email'] === ''){
        $('#RegisterForm').find('[name = "email"]').siblings('.error').text('请输入邮箱');
        return
    }
     if(hash['password'] === ''){
        $('#RegisterForm').find('[name = "password"]').siblings('.error').text('请输入密码');
        return
    }
    if(hash['password_confirm'] === ''){
        $('#RegisterForm').find('[name = "password_confirm"]').siblings('.error').text('请输入密码');
        return
    }
    if(hash['password'] !== hash['password_confirm'] ){
        $('#RegisterForm').find('[name = "password_confirm"]').siblings('.error').text('密码不匹配');
        return
    }

3.ajax发送post请求register页面:

如果请求成功,打印出返回的信息;
如果请求失败,判断一下失败信息,然后给出错误信息提示;

    $.post('/register',hash).then((response) =>{console.log(response)},
        (request) => {
        let {errors} = request.responseJSON;/*等价于----
-------let {errors} = JSON.parse(request.responseText)*/
        if(errors.email  &&  errors.email === 'invalid'){
           $('#RegisterForm').find('[name = "email"]')
.siblings('.error').text('邮箱输错了');
        }
        })
    })

4.服务端代码:

给register页面的(发送POST请求)设置路由,
后端代码将浏览器传来的request中的信息存储到hash中,判断是否符合输入要求,同时判断邮箱是否唯一,如果不符合,服务器返回400,给出提示;如果符合,返回200,将数据信息存储到本地数据库./db/users

else if(path === '/register' && method ==='POST'){
        readBody(request).then((body) => {
            let strings = body.split('& ');
            let hash = {};
            strings.forEach((string) => {
                let parts = string.split('=');
                let key = parts[0];
                let value = parts[1];
                hash[key] = decodeURIComponent(value) ;//解决url路径解析不了@符号的问题
               })
                let {email, password, password_confirm} = hash;

                if (email.indexOf('@') === -1) {
                    response.statusCode = 400;
                    response.setHeader('Content-Type', 'text/json;charset=utf-8')
                    response.write(`{"errors":
                    {"email":"invalid"}
                    }`);
                }
                else if (password !== password_confirm) {
                    response.statusCode = 400;
                    response.write('password not match');
                }
                else {
                    var users = fs.readFileSync('./db/users','utf8')
                    try{
                         users = JSON.parse(users)
                    }
                    catch(exception) {
                        users = [];
                    }
                    let inUse = false;
                    for(let i = 0;i<users.length;i++){
                        let user = users[i];
                        if(user.email = email)
                        {inUse = true}
                    }
                    if(inUse){
                        response.statusCode = 400
                        response.write('email inUse');
                    }else{
                        users.push({ email: email, password: password })
                        response.statusCode = 200
                        let usersString = JSON.stringify(users)
                        fs.writeFileSync('./db/users',usersString);
                    }
                }
               response.end()
        })
    }
function readBody(request){  //用来读取整段的浏览器传来的formdata,因为浏览器是片段上传的方式
    return new Promise((resolve,reject) => {
        let body = [];
        request.on('data',(chunk) => {
            body.push(chunk)
        }).on('end',() => {
            body = Buffer.concat(body).toString();
            resolve(body);
        })
    })
}

二·登录界面

功能:

  • 判断用户输入的邮箱,密码是否为空(前端判断)
  • 判断用户输入的邮箱是否正确(后端判断)
  • 判断输入的密码是否正确(后端判断)

1.html部分:

<div class="form-wrapper">
    <h1>登录</h1>
    <form id="loginForm" >
        <div class="row">
            <lable>邮箱</lable>
            <input type="text" name="email">
            <span class="error"></span>
        </div>
        <div class="row">
            <lable>密码</lable>
            <input type="password" name="password">
            <span class="error"></span>
        </div>

        <div class="row">
            <input type="submit">
        </div>

    </form>
</div>

2.JS部分:

将用户填写的登录信息存储到hash表中,如果用户输入为空,则给出错误信息提示

  $('#loginForm').on('submit',(e) => {
        e.preventDefault();
        let hash = {};
        let arg = ['email','password'];
        arg.forEach((name) => {
            let value = $('#loginForm').find(`[name= ${name}]`).val();
            hash[name] = value;
        })
        $('#loginForm').find('.error').each((index,span) => {
            $(span).text('');
        })
        if(hash['email'] === ''){
            $('#loginForm').find('[name = "email"]').siblings('.error').text('请输入邮箱');
            return
        }
        if(hash['password'] === ''){
            $('#loginForm').find('[name = "password"]').siblings('.error').text('请输入密码');
            return
        }

3.ajax发送post请求login页面:

如果请求成功,跳转到首页;如果请求失败,给出登录失败的提示

     $.post('/login',hash).then(() =>{window.location.href="/"},
         () => {
              alert("登录失败,请重新登录")
          })
    })

4.给login页面(post请求)设置路由:

读取本地数据库./db/users,与浏览器传来的formdata进行比对,如果用户密码正确,给浏览器设置cookie,将用户登录的邮箱名存下来,返回200

 else if(path==='/login' && method ==="POST"){
        readBody(request).then((body) => {
            let strings = body.split('&');
            let hash = {};
            strings.forEach((string) => {
                let parts = string.split('=');
                let key = parts[0];
                let value = parts[1];
                hash[key] = decodeURIComponent(value);
            })
            let {email, password} = hash;
            var users = fs.readFileSync('./db/users','utf8')
            try{
                users = JSON.parse(users)
            }
            catch(exception) {
                users = [];
            }
            let found ;
            for(let i = 0;i<users.length;i++){
                let user = users[i];
                if(user.email === email && user.password === password)
                {found = true;
                break;}
            }
            if(found){
                /*设置cookie,将用户的登录邮箱名存下来*/
                response.setHeader('set-cookie',`email= ${email}`);
                response.statusCode = 200

            }else{
                response.statusCode = 401
            }
            response.end();
        })

    }

这里讲到了给浏览器设置cookie,我们就来简单了解一下什么是cookie。

三·cookie

cookie指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)
服务器通过set-cookie后,给浏览器传了一段识别身份的数据;之后浏览器给次请求都会附上这份cookie数据,服务器以此来验明浏览器的身份。cookie的时效性一般是两天左右,可以自行设置。
通俗的来讲就是cookie就是一个验证身份的门票,服务器给浏览器发了一张门票,浏览器请求数据时需要拿出门票,服务器看到门票后验证了身份,才会同意请求。
这里值得注意的是cookie的作用域domain,cookie也遵守浏览器同源策略,不同域名的cookie的是不一样的。

四·登录后跳转首页

登录界面获取到浏览器设置的cookie,再次向服务器请求跳转到首页时需要附上这段cookie,服务器读取后同意跳转到首页。
功能:

  • 若登录成功,跳转到首页,在首页显示登录邮箱名

1.html部分(首页):

<body>
<h1>这是首页</h1>
<span>用户: --email--</span>
</body>

2.给首页设置路由:

读取cookie值,展示在首页上,显示当前登录的用户邮箱名

 else if(path === '/'){
        let string = fs.readFileSync('./index.html', 'utf8')
        let cookies = request.headers.cookie.split('; ');/*这里多出一个空格,要注意*/
        let hash = {};
        for(let i =0 ;i<cookies.length;i++){
            let parts = cookies[i].split('=');
            let key = parts[0];
            let value = parts[1];
            hash[key] = value;
        }

总结

讲解完实现过程后,我们来总结一下:
当我们进行登录注册时,网页都做了些什么呢?
1.我们进行注册时,浏览器向服务器发送post请求,同时将注册信息传过去;
2.服务器将用户信息存储到本地数据库后,告知浏览器注册成功
3.用户打开登录界面,输入登录信息,向服务器发送post请求
4.服务器读取本地数据库,比对登录信息是否正确,若错误,告知浏览器登录失败;若正确给浏览器设置cookie
5.浏览器向服务器发送get请求,访问首页,附上cookie
6.服务器读取cookie,验证身份后,同意浏览器访问首页

源码
附上一个vue版本带有登录注册功能的备忘录demo

以上是个人观点,如有错误欢迎指出。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容

  • HTTP cookie(也称为web cookie,网络cookie,浏览器cookie或者简称cookie)是网...
    留七七阅读 17,809评论 2 71
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • 窗前依旧孱动着人影 车轮惊醒了 月光的余温 幽暗的歌声并没有远去 夜的孤独偷偷降临 死亡的灵魂 渐渐苏醒 可怕的白...
    身后一扇窗阅读 186评论 0 0
  • 心若安,可步步生莲 心若安,可步步生莲。心清一切明,心浊一切暗;心痴一切迷,心悟一切禅。心是人生戏的导演,念是人生...
    xcy无名阅读 419评论 0 0
  • 清澈的眸子 只那一眼 我便看穿了你 仿佛我俩从未断了联系 —如今的你...
    与影相随4阅读 329评论 6 3