【实战】js+node.js实现注册登录 发表于 2018-11-05 | 分类于 JavaScript 登录与注册UIdribbble 流程1.需求分析 登录(邮箱、密码) 注册(邮箱、密码、重复密码) 重置密码(邮箱) 已登录 2.寻找后端代码 LeanCloud 或者用Node.js写一个后端,然后买一个服务器或VPS来运行Node.js,确保接口可用 3.写代码-测试-部署-改进 注册表单前端代码123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103<!DOCTYPE html><html lang="zh-Hans"><head> <meta charset="UTF-8"> <title>登录</title></head><body> <section> <h1>登录</h1> <form name="login" action="/login" method="post"> <div> <label>邮箱 <input type="text" name="email"> </label> </div> <div> <label>密码 <input type="password" name="password"> </label> </div> <input type="submit" value="登录"> </form> </section> <section> <h1>注册</h1> <form name="signUp" action="/signUp" method="post"> <div> <label>邮箱 <input type="text" name="email"> </label> <span name="email_error" class="error"></span> </div> <div> <label>密码 <input type="password" name="password"> </label> <span name="password_error" class="error"></span> </div> <div> <label>确认密码 <input type="password" name="password_confirmation"> </label> <span name="password_confirmation_error" class="error"></span> </div> <input type="submit" value="注册"> </form> </section> <section> <h1>重置密码</h1> <form name="resetPassword" action="/resetPassword" method="post"> <div> <label>重置密码 <input type="text" name="email"> </label> </div> <input type="submit" value="请求重置密码"> </form> </section> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script src="main.js"></script></body></html>// main.jslet $signUpFrom = $('form[name=signUp]')$signUpFrom.on('submit',(e)=>{ e.preventDefault() let string = $signUpFrom.serialize() let email = $signUpFrom.find('[name=email]').val() let password = $signUpFrom.find('[name=password]').val() let password_confirmation = $signUpFrom.find('[name=password_confirmation]').val() let errors = {} // check email if(email.indexOf('@') <= 0){ errors.email = '邮箱不合法' } if(password.length < 6){ errors.password = '密码太短' } if(password_confirmation !== password){ errors.password_confirmation = '两次输入密码不匹配' } $signUpFrom.find('span[name$=_error]').each(function(){ $(this).text('') }) if (Object.keys(errors).length !==0) { for(var key in errors){ let value = errors[key] $signUpFrom.find(`span[name=${key}_error]`).text(value) } return } $.ajax({ url: $signUpFrom.attr('action'), method: $signUpFrom.attr('method'), data: string, success: function(response){ let object = JSON.parse(response) //浏览器上运行 console.log(object) } })}) 后台代码1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980// server.jsvar http = require('http')var fs = require('fs')var url = require('url')var port = process.argv[2]if(!port){ console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?') process.exit(1)}var server = http.createServer(function(request, response){ var parsedUrl = url.parse(request.url, true) var pathWithQuery = request.url var queryString = '' if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) } var path = parsedUrl.pathname var query = parsedUrl.query var method = request.method /******** 从这里开始看,上面不要看 ************/ if(path === '/'){ response.statusCode = 200 var string = fs.readFileSync('./index.html') response.setHeader('Content-Type', 'text/html;charset=utf-8') response.end(string) }else if(path === '/signUp' && method === 'POST'){ getPostData(request,function(postData){ let {email,password,password_confirmation} = postData let errors = {} // check email if(email.indexOf('@') <= 0){ errors.email = '邮箱不合法' } if(password.length < 6){ errors.password = '密码太短' } if(password_confirmation !== password){ errors.password_confirmation = '两次输入密码不匹配' } response.setHeader('Content-Type', 'text/html;charset=utf-8') response.end(JSON.stringify(errors)) }) }else if(path === '/main.js'){ let string = fs.readFileSync('./main.js') response.setHeader('Content-Type', 'text/html;charset=utf-8') response.end(string) }else{ response.statusCode = 404 response.setHeader('Content-Type', 'text/html;charset=utf-8') response.end('找不到对应的路径,你需要自行修改index.js') } /******** 代码结束,下面不要看 ************/ console.log(method + ' ' + request.url)})function getPostData(request,callback){ data = '' request.on('data',(postData) =>{ data += postData.toString() }) request.on('end',()=>{ let array = data.split('&') let postData = {} for (var i = 0; i < array.length; i++) { let parts = array[i].split('=') let key = decodeURIComponent(parts[0]) let value = decodeURIComponent(parts[1]) postData[key] = value } callback.call(null,postData) })}server.listen(port)console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port) 登录表单前端代码123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145// index.html<!DOCTYPE html><html lang="zh-Hans"><head> <meta charset="UTF-8"> <title>登录</title></head><body> <section> <h1>登录</h1> <form name="login" action="/login" method="post"> <div> <label>邮箱 <input type="text" name="email"> </label> </div> <div> <label>密码 <input type="password" name="password"> </label> </div> <input type="submit" value="登录"> </form> </section> <section> <h1>注册</h1> <form name="signUp" action="/signUp" method="post"> <div> <label>邮箱 <input type="text" name="email"> </label> <span name="email_error" class="error"></span> </div> <div> <label>密码 <input type="password" name="password"> </label> <span name="password_error" class="error"></span> </div> <div> <label>确认密码 <input type="password" name="password_confirmation"> </label> <span name="password_confirmation_error" class="error"></span> </div> <input type="submit" value="注册"> </form> </section> <section> <h1>重置密码</h1> <form name="resetPassword" action="/resetPassword" method="post"> <div> <label>重置密码 <input type="text" name="email"> </label> </div> <input type="submit" value="请求重置密码"> </form> </section> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script src="main.js"></script></body></html>// home.html<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>首页</title></head><body> <h1>首页</h1></body></html>// main.js// 登录let $loginForm = $('form[name=login]')$loginForm.on('submit',(e)=>{ e.preventDefault() let string = $loginForm.serialize() $.ajax({ url: $loginForm.attr('action'), method: $loginForm.attr('method'), data: string, success: function(){ location.href = './home' }, error: function(){} })})// 注册let $signUpFrom = $('form[name=signUp]')$signUpFrom.on('submit',(e)=>{ e.preventDefault() let string = $signUpFrom.serialize() // check email let errors = checkForm($signUpFrom) if (Object.keys(errors).length !==0) { showErrors($signUpFrom,errors) }else{ $.ajax({ url: $signUpFrom.attr('action'), method: $signUpFrom.attr('method'), data: string, success: function(response){ location.href = './home' }, error: function(xhr){ let errors = JSON.parse(xhr.responseText) showErrors($signUpFrom,errors) } }) }})function checkForm($signUpFrom){ let email = $signUpFrom.find('[name=email]').val() let password = $signUpFrom.find('[name=password]').val() let password_confirmation = $signUpFrom.find('[name=password_confirmation]').val() let errors = {} if(email.indexOf('@') <= 0){ errors.email = '邮箱不合法' } if(password.length < 6){ errors.password = '密码太短' } if(password_confirmation !== password){ errors.password_confirmation = '两次输入密码不匹配' } return errors}function showErrors($signUpFrom,errors){ $signUpFrom.find('span[name$=_error]').each(function(){ $(this).text('') }) for(var key in errors){ let value = errors[key] $signUpFrom.find(`span[name=${key}_error]`).text(value) }} 后端代码123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165// server.jsvar http = require('http')var fs = require('fs')var url = require('url')var port = process.argv[2]if(!port){ console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?') process.exit(1)}var server = http.createServer(function(request, response){ var parsedUrl = url.parse(request.url, true) var pathWithQuery = request.url var queryString = '' if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) } var path = parsedUrl.pathname var query = parsedUrl.query var method = request.method /******** 从这里开始看,上面不要看 ************/ if(path === '/'){ response.statusCode = 200 var string = fs.readFileSync('./index.html') response.setHeader('Content-Type', 'text/html;charset=utf-8') response.end(string) }else if(path === '/signUp' && method === 'POST'){ getPostData(request,function(postData){ let errors = checkPostData(postData) if(Object.keys(errors).length === 0){ let {email,password} = postData let user = { email : email, passwordHash : yangHash(password) } // 写数据库 let dbString = fs.readFileSync('./db.json','utf-8') let dbObject = JSON.parse(dbString) dbObject.users.push(user) let dbString2 = JSON.stringify(dbObject) fs.writeFileSync('./db.json',dbString2,{encoding: 'utf-8'}) }else{ response.statusCode = 400 } response.setHeader('Content-Type', 'text/html;charset=utf-8') response.end(JSON.stringify(errors)) }) }else if(path === '/login' && method === 'POST'){ // 读数据库 getPostData(request,function(postData){ let dbString = fs.readFileSync('./db.json','utf-8') let dbObject = JSON.parse(dbString) let users = dbObject.users let {email,password} = postData let found for(var i = 0;i < users.length;i++){ if (users[i].email === email && users[i].passwordHash === yangHash(password)) { found = users[i] break } } if(found){ // 标记该用户登录 response.setHeader('Set-Cookie',['logined=true;expires=1000;path=/;','user_id='+email+'; expires=123456789;path=/;']) response.end('') }else{ response.statusCode = 400 let errors = { email : '没有注册或密码错误'} response.setHeader('Content-Type', 'text/html;charset=utf-8') response.end(JSON.stringify(errors)) } }) }else if(path === '/main.js'){ let string = fs.readFileSync('./main.js') response.setHeader('Content-Type', 'application/javascript;charset=utf-8') response.end(string) }else if(path === '/home'){ var cookies = parseCookies(request.headers.cookie) response.setHeader('Content-Type', 'text/html;charset=utf-8') if (cookies.logined === 'true') { response.end(`${cookies.user_id}已登录`) }else{ let string = fs.readFileSync('./home.html') response.end(string) } }else{ response.statusCode = 404 response.setHeader('Content-Type', 'text/html;charset=utf-8') response.end('找不到对应的路径,你需要自行修改index.js') } /******** 代码结束,下面不要看 ************/ console.log(method + ' ' + request.url)})function getPostData(request,callback){ data = '' request.on('data',(postData) =>{ data += postData.toString() }) request.on('end',()=>{ let array = data.split('&') let postData = {} for (var i = 0; i < array.length; i++) { let parts = array[i].split('=') let key = decodeURIComponent(parts[0]) let value = decodeURIComponent(parts[1]) postData[key] = value } callback.call(null,postData) })}function checkPostData(postData){ let {email,password,password_confirmation} = postData let errors = {} // check email if(email.indexOf('@') <= 0){ errors.email = '邮箱不合法' } if(password.length < 6){ errors.password = '密码太短' } if(password_confirmation !== password){ errors.password_confirmation = '两次输入密码不匹配' } return errors}function yangHash(string){ return 'yang' + string + 'yang'}function parseCookies(cookie) { // JSON.parse try{ return cookie.split(';').reduce( function(prev, curr) { var m = / *([^=]+)=(.*)/.exec(curr); var key = m[1]; var value = decodeURIComponent(m[2]); prev[key] = value; return prev; }, { } ); }catch(error){ return {} }}function stringifyCookies(cookies) { //JSON.stringify var list = [ ]; for (var key in cookies) { list.push(key + '=' + encodeURIComponent(cookies[key])); } return list.join('; ');}server.listen(port)console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)// db.json{"users":[]}