这次给大家带来使用cookie保持登录状态步骤详解,使用cookie保持登录状态的注意事项有哪些,下面就是实战案例,一起来看一下。
这次来做一个网站登录的小例子,后面会用到。这个示例会用到Cookie、HTML表单、POST数据体(body)解析。
第一个版本,我们的用户数据就写死在js文件里。第二个版本会引入MongoDB来保存用户数据。
示例准备
1. 使用express创建应用
就下面的命令序列:
express LoginDemo cd LoginDemo npm install
2. 登录页面
登录页面的jade模板为login.jade,内容如下:
doctype html html head meta(charset='UTF-8') title 登录 link(rel='stylesheet', href='/stylesheets/login.css') body .form-container p.form-header 登录 form(action='login', method='POST', align='center') table tr td label(for='user') 账号: td input#user(type='text', name='login_username') tr td label(for='pwd') 密码: td input#pwd(type='password', name='login_password') tr td(colspan='2', align='right') input(type='submit', value='登录') p #{msg}
login.jade放在views目录下。我在login.jade里硬编码了汉字,注意文件用UTF-8编码。
这个模板的最后是一条动态消息,用于显示登录错误信息,msg变量由应用程序传入。
我给login页面写了个简单的CSS,login.css文件,内容如下:
form { margin: 12px; } a { color: #00B7FF; } p.form-container { display: inline-block; border: 6px solid steelblue; width: 280px; border-radius: 10px; margin: 12px; } p.form-header { margin: 0px; font: 24px bold; color: white; background: steelblue; text-align: center; } input[type=submit]{ font: 18px bold; width: 120px; margin-left: 12px; }
请把login.css放在public/stylesheets目录下。
3. profile页面
登录成功后会显示配置页面,profile.jade页面内容:
doctype html html head meta(charset='UTF-8') title= title body p #{msg} p #{lastTime} p a(href='/logout') 退出
profile.jade放在views目录下。profile页面显示一条登录成功的消息,还显示上次登录时间,最后提供了一个退出链接。
4. app.js改动
我改动了app.js,以便用户在没有登录时访问网站自动跳转到login页面。新的app.js内容如下:
var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var users = require('./routes/users'); var app = express(); // view engine setup app.set('views', path.join(dirname, 'views')); app.set('view engine', 'jade'); // uncomment after placing your favicon in /public //app.use(favicon(path.join(dirname, 'public', 'favicon.ico'))); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(dirname, 'public'))); app.all('*', users.requireAuthentication); app.use('/', users); // catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); // error handlers // development error handler // will print stacktrace if (app.get('env') === 'development') { app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: err }); }); } // production error handler // no stacktraces leaked to user app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: {} }); }); module.exports = app;
5. users.js
我修改了users.js,把认证、登录、登出等逻辑放在里面,首先要把users.js转为UTF-8编码(sorry,硬编码了汉字哈)。内容:
var express = require('express'); var router = express.Router(); var crypto = require('crypto'); function hashPW(userName, pwd){ var hash = crypto.createHash('md5'); hash.update(userName + pwd); return hash.digest('hex'); } // just for tutorial, it's bad really var userdb = [ { userName: "admin", hash: hashPW("admin", "123456"), last: "" }, { userName: "foruok", hash: hashPW("foruok", "888888"), last: "" } ]; function getLastLoginTime(userName){ for(var i = 0; i < userdb.length; ++i){ var user = userdb[i]; if(userName === user.userName){ return user.last; } } return ""; } function updateLastLoginTime(userName){ for(var i = 0; i < userdb.length; ++i){ var user = userdb[i]; if(userName === user.userName){ user.last = Date().toString(); return; } } } function authenticate(userName, hash){ for(var i = 0; i < userdb.length; ++i){ var user = userdb[i]; if(userName === user.userName){ if(hash === user.hash){ return 0; }else{ return 1; } } } return 2; } function isLogined(req){ if(req.cookies["account"] != null){ var account = req.cookies["account"]; var user = account.account; var hash = account.hash; if(authenticate(user, hash)==0){ console.log(req.cookies.account.account + " had logined."); return true; } } return false; }; router.requireAuthentication = function(req, res, next){ if(req.path == "/login"){ next(); return; } if(req.cookies["account"] != null){ var account = req.cookies["account"]; var user = account.account; var hash = account.hash; if(authenticate(user, hash)==0){ console.log(req.cookies.account.account + " had logined."); next(); return; } } console.log("not login, redirect to /login"); res.redirect('/login?'+Date.now()); }; router.post('/login', function(req, res, next){ var userName = req.body.login_username; var hash = hashPW(userName, req.body.login_password); console.log("login_username - " + userName + " password - " + req.body.login_password + " hash - " + hash); switch(authenticate(userName, hash)){ case 0: //success var lastTime = getLastLoginTime(userName); updateLastLoginTime(userName); console.log("login ok, last - " + lastTime); res.cookie("account", {account: userName, hash: hash, last: lastTime}, {maxAge: 60000}); res.redirect('/profile?'+Date.now()); console.log("after redirect"); break; case 1: //password error console.log("password error"); res.render('login', {msg:"密码错误"}); break; case 2: //user not found console.log("user not found"); res.render('login', {msg:"用户名不存在"}); break; } }); router.get('/login', function(req, res, next){ console.log("cookies:"); console.log(req.cookies); if(isLogined(req)){ res.redirect('/profile?'+Date.now()); }else{ res.render('login'); } }); router.get('/logout', function(req, res, next){ res.clearCookie("account"); res.redirect('/login?'+Date.now()); }); router.get('/profile', function(req, res, next){ res.render('profile',{ msg:"您登录为:"+req.cookies["account"].account, title:"登录成功", lastTime:"上次登录:"+req.cookies["account"].last }); }); module.exports = router;
如你所见,我内置了两个账号,admin和foruok,登录时就验证这两个账号,不对就报错。
好了,执行“npm start”,然后在浏览器里打开“http://localhost:3000”,可以看到下面的效果:
折腾几次,登录,退出,再次登录,效果如下:
好啦,这就是这个示例的效果。接下来我们来解释一下用到概念和部分代码。
处理POST正文数据
我们在示例中使用了HTML表单来接收用户名和密码,当input元素的类型为submit时,点击它,浏览器会把表单内的数据按一定的格式组织之后编码进body,POST到指定的服务器地址。用户名和密码,在服务器端,可以通过HTML元素的名字属性的值找出来。
服务器解析表单数据这一过程,我们不用担心,用了express的body-parser中间件,它会帮我们做这件事,只要做简单的配置即可。而且这些配置代码,express generator都帮我们完成了,如下:
//加载body-parser模块 var bodyParser = require('body-parser'); ... //应用中间件 app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false }));
我们处理/login路径上的POST请求的代码在users.js里,从“router.post(‘/login'…”开始(94行,要是markdown能自动给代码插入行号就好了)。引用登录表单内的用户名的代码如下:
var userName = req.body.login_username;
注意到了吧,express.Request对象req内有解析好的body,我们使用login_username来访问用户名。而login_username就是我们在HTML里的input元素的name属性的值。就这么关联的。password也类似。
cookie
cookie,按我的理解,就是服务器发给浏览器的一张门票,要访问服务器内容,可以凭票入场,享受某种服务。服务器可以在门票上记录一些信息,从技术角度讲,想记啥记啥。当浏览器访问服务器时,HTTP头部把cookie信息带到服务器,服务器解析出来,校验当时记录在cookie里的信息。
HTTP协议本身是无状态的,而应用服务器往往想保存一些状态,cookie应运而生,由服务器颁发,通过HTTP头部传给浏览器,浏览器保存到本地。后续访问服务器时再通过HTTP头部传递给服务器。这样的交互,服务器就可以在cookie里记录一些用户相关的信息,比如是否登录了,账号了等等,然后就可以根据这些信息做一些动作,比如我们示例中的持久登录的实现,就利用了cookie。还有一些电子商务网站,实现购物车时也可能用到cookie。
cookie存储的是一些key-value对。在express里,Request和Response都有cookie相关的方法。Request实例req的cookies属性,保存了解析出的cookie,如果浏览器没发送cookie,那这个cookies对象就是一个空对象。
express有个插件,cookie-parser,可以帮助我们解析cookie。express生成的app.js已经自动为我们配置好了。相关代码:
var cookieParser = require('cookie-parser'); ... app.use(cookieParser());
express的Response对象有一个cookie方法,可以回写给浏览器一个cookie。
下面的代码发送了一个名字叫做“account”的cookie,这个cookie的值是一个对象,对象内有三个属性。
复制代码 代码如下:
res.cookie("account", {account: userName, hash: hash, last: lastTime}, {maxAge: 60000});
res.cookie()方法原型如下:
res.cookie(name, value [, options])
文档在这里:http://expressjs.com/4x/api.html。
浏览器会解析HTTP头部里的cookie,根据过期时间决定保存策略。当再次访问服务器时,浏览器会把cookie带给服务器。服务器使用cookieParser解析后保存在Request对象的cookies属性里,req.cookies本身是一个对象,解析出来的cookie,会被关联到req.cookies的以cookie名字命名的属性上。比如示例给cookie起的名字叫account,服务端解析出的cookie,就可以通过req.cookies.account来访问。注意req.cookies.account本身既可能是简单的值也可能是一个对象。在示例中通过res.cookie()发送的名为account的cookie,它的值是一个对象,在这种情况下,服务器这边从HTTP请求中解析出的cookie也会被组装成一个对象,所以我们通过req.cookies.account.account就可以拿到浏览器通过cookie发过来的用户名。但如果浏览器没有发送名为“account”的cookie,那req.cookies.account.hash这种访问就会抛异常,所以我在代码里使用req.cookies[“account”]这种方式来检测是否有account这个cookie。
持久登录
如果用户每次访问一个需要鉴权的页面都要输入用户名和密码来登录,那就太麻烦了。所以,很多现代的网站都实现了持久登录。我的示例使用cookie简单实现了持久登录。
在处理/login路径上的POST请求时,如果登录成功,就把用户名、一个hash值、还有上次登录时间保存在cookie里,并且设置cookie的有效期为60秒。这样在60秒有效期内,浏览器后续的访问就会带cookie,服务端代码从cookie里验证用户名和hash值,让用户保持登录状态。当过了60秒,浏览器就不再发送cookie,服务端就认为需要重新登录,将用户重定向到login页面。
现在服务端的用户信息就简单的放在js代码里了,非常丑陋,下次我们引入MongoDB,把用户信息放在数据库里。
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
Atas ialah kandungan terperinci 使用cookie保持登录状态步骤详解. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Aplikasi JavaScript di dunia nyata termasuk pengaturcaraan sisi pelayan, pembangunan aplikasi mudah alih dan Internet of Things Control: 1. Pengaturcaraan sisi pelayan direalisasikan melalui node.js, sesuai untuk pemprosesan permintaan serentak yang tinggi. 2. Pembangunan aplikasi mudah alih dijalankan melalui reaktnatif dan menyokong penggunaan silang platform. 3. Digunakan untuk kawalan peranti IoT melalui Perpustakaan Johnny-Five, sesuai untuk interaksi perkakasan.

Saya membina aplikasi SaaS multi-penyewa berfungsi (aplikasi edTech) dengan alat teknologi harian anda dan anda boleh melakukan perkara yang sama. Pertama, apakah aplikasi SaaS multi-penyewa? Aplikasi SaaS Multi-penyewa membolehkan anda melayani beberapa pelanggan dari Sing

Artikel ini menunjukkan integrasi frontend dengan backend yang dijamin oleh permit, membina aplikasi edtech SaaS yang berfungsi menggunakan Next.Js. Frontend mengambil kebenaran pengguna untuk mengawal penglihatan UI dan memastikan permintaan API mematuhi dasar peranan

JavaScript adalah bahasa utama pembangunan web moden dan digunakan secara meluas untuk kepelbagaian dan fleksibiliti. 1) Pembangunan front-end: Membina laman web dinamik dan aplikasi satu halaman melalui operasi DOM dan kerangka moden (seperti React, Vue.js, sudut). 2) Pembangunan sisi pelayan: Node.js menggunakan model I/O yang tidak menyekat untuk mengendalikan aplikasi konkurensi tinggi dan masa nyata. 3) Pembangunan aplikasi mudah alih dan desktop: Pembangunan silang platform direalisasikan melalui reaktnatif dan elektron untuk meningkatkan kecekapan pembangunan.

Trend terkini dalam JavaScript termasuk kebangkitan TypeScript, populariti kerangka dan perpustakaan moden, dan penerapan webassembly. Prospek masa depan meliputi sistem jenis yang lebih berkuasa, pembangunan JavaScript, pengembangan kecerdasan buatan dan pembelajaran mesin, dan potensi pengkomputeran IoT dan kelebihan.

JavaScript adalah asas kepada pembangunan web moden, dan fungsi utamanya termasuk pengaturcaraan yang didorong oleh peristiwa, penjanaan kandungan dinamik dan pengaturcaraan tak segerak. 1) Pengaturcaraan yang didorong oleh peristiwa membolehkan laman web berubah secara dinamik mengikut operasi pengguna. 2) Penjanaan kandungan dinamik membolehkan kandungan halaman diselaraskan mengikut syarat. 3) Pengaturcaraan Asynchronous memastikan bahawa antara muka pengguna tidak disekat. JavaScript digunakan secara meluas dalam interaksi web, aplikasi satu halaman dan pembangunan sisi pelayan, sangat meningkatkan fleksibiliti pengalaman pengguna dan pembangunan silang platform.

Python lebih sesuai untuk sains data dan pembelajaran mesin, manakala JavaScript lebih sesuai untuk pembangunan front-end dan penuh. 1. Python terkenal dengan sintaks ringkas dan ekosistem perpustakaan yang kaya, dan sesuai untuk analisis data dan pembangunan web. 2. JavaScript adalah teras pembangunan front-end. Node.js menyokong pengaturcaraan sisi pelayan dan sesuai untuk pembangunan stack penuh.

JavaScript tidak memerlukan pemasangan kerana ia sudah dibina dalam pelayar moden. Anda hanya memerlukan editor teks dan penyemak imbas untuk memulakan. 1) Dalam persekitaran penyemak imbas, jalankan dengan memasukkan fail HTML melalui tag. 2) Dalam persekitaran Node.js, selepas memuat turun dan memasang node.js, jalankan fail JavaScript melalui baris arahan.


Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

MinGW - GNU Minimalis untuk Windows
Projek ini dalam proses untuk dipindahkan ke osdn.net/projects/mingw, anda boleh terus mengikuti kami di sana. MinGW: Port Windows asli bagi GNU Compiler Collection (GCC), perpustakaan import yang boleh diedarkan secara bebas dan fail pengepala untuk membina aplikasi Windows asli termasuk sambungan kepada masa jalan MSVC untuk menyokong fungsi C99. Semua perisian MinGW boleh dijalankan pada platform Windows 64-bit.

Penyesuai Pelayan SAP NetWeaver untuk Eclipse
Integrasikan Eclipse dengan pelayan aplikasi SAP NetWeaver.

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

Dreamweaver Mac版
Alat pembangunan web visual

SublimeText3 Linux versi baharu
SublimeText3 Linux versi terkini