Dieses Mal zeige ich Ihnen, wie Sie Node.js zum Betreiben von Cookies verwenden, um angemeldet zu bleiben. Welche Vorsichtsmaßnahmen gelten für die Verwendung von Node.js zum Betreiben von Cookies, um angemeldet zu bleiben. Hier sind praktische Fälle , lass uns einen Blick darauf werfen.
Dieses Mal werde ich ein kleines Beispiel für die Website-Anmeldung erstellen, das später verwendet wird. In diesem Beispiel werden Cookies, HTML-Formular und die Analyse des POST-Datenkörpers (Body) verwendet.
In der ersten Version werden unsere Benutzerdaten in die js-Datei geschrieben. Die zweite Version führt MongoDB ein, um Benutzerdaten zu speichern.
Beispielvorbereitung
1. Verwenden Sie Express, um eine Anwendung zu erstellen
Die folgende Befehlssequenz :
express LoginDemo cd LoginDemo npm install
2. Die Jade-Vorlage der Anmeldeseite
ist login.jade und der Inhalt lautet wie folgt:
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 wird im View-Verzeichnis Down abgelegt. Ich habe chinesische Zeichen in login.jade fest codiert. Beachten Sie, dass die Datei in UTF-8 codiert ist.
Am Ende dieser Vorlage befindet sich eine dynamische Nachricht zur Anzeige der Anmelde-Fehlermeldung. Die msg-Variable wird von der Anwendung übergeben.
Ich habe ein einfaches CSS für die Anmeldeseite geschrieben, die Datei login.css. Der Inhalt lautet wie folgt:
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; }
Bitte legen Sie login.css im Verzeichnis public/stylesheets ab.
3. Profilseite
Nach erfolgreicher Anmeldung wird der Inhalt der Seite „profile.jade“ angezeigt:
doctype html html head meta(charset='UTF-8') title= title body p #{msg} p #{lastTime} p a(href='/logout') 退出
profile.jade wird im Verzeichnis „Ansichten“ abgelegt. Auf der Profilseite wird eine Meldung über die erfolgreiche Anmeldung, außerdem die letzte Anmeldezeit und schließlich ein Abmeldelink angezeigt.
4. App.js-Änderungen
Ich habe app.js so geändert, dass Benutzer automatisch zur Anmeldeseite springen können, wenn sie die Website besuchen, ohne sich anzumelden. Der neue Inhalt von app.js lautet wie folgt:
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
Ich habe „users.js“ geändert und Authentifizierung, Anmeldung, Abmeldung und andere Logik eingefügt Im Inneren müssen Sie zunächst „users.js“ in die UTF-8-Kodierung konvertieren (chinesische Schriftzeichen sind leider fest kodiert). Inhalt:
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;
Wie Sie sehen können, habe ich zwei Konten eingebaut, admin und foruok. Beim Anmelden werde ich diese beiden Konten überprüfen und einen Fehler melden, wenn sie nicht korrekt sind.
Okay, führen Sie „npm start“ aus und öffnen Sie dann „http://localhost:3000“ im Browser. Sie können den folgenden Effekt sehen:
Nachdem Sie es ein paar Mal geworfen haben, melden Sie sich an, melden Sie sich ab und wieder an. Der Effekt ist wie folgt:
Okay, das ist der Effekt dieses Beispiels. Als nächstes erklären wir die Konzepte und einige verwendete Codes.
Verarbeitung von POST-Körperdaten
Wir verwenden im Beispiel ein HTML-Formular, um Benutzernamen und Passwort zu empfangen, wenn der Typ des Eingabeelements „Senden“ ist , klicken Sie darauf, der Browser organisiert die Daten im Formular in einem bestimmten Format, kodiert sie in den Textkörper und sendet einen POST an die angegebene Serveradresse. Der Benutzername und das Passwort können serverseitig über den Wert des Namensattributs des HTML-Elements ermittelt werden.
Wir müssen uns nicht um den Prozess der Analyse der Formulardaten kümmern. Wir verwenden die Body-Parser-Middleware von Express, die dies für uns erledigt. Und der Express-Generator hat uns dabei geholfen, diese Konfigurationscodes wie folgt zu vervollständigen:
//加载body-parser模块 var bodyParser = require('body-parser'); ... //应用中间件 app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false }));
Unser Code für die Verarbeitung von POST-Anfragen auf dem /login-Pfad befindet sich in „users.js“ unter „router.post('/login‘. . „Start (Zeile 94, es wäre toll, wenn Markdown automatisch Zeilennummern in den Code einfügen könnte). Der Code, der sich auf den Benutzernamen im Anmeldeformular bezieht, lautet wie folgt:
var userName = req.body.login_username;
Habe bemerkt, dass es so ist Parsen in express.Request-Objektanforderung Okay, wir verwenden login_username, um auf den Benutzernamen zuzugreifen. Der login_username ist der Wert des Namensattributs unseres Eingabeelements. Das Passwort ist ähnlich
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中文网其它相关文章!
推荐阅读:
Das obige ist der detaillierte Inhalt vonSo manipulieren Sie Cookies mit Node.js, um angemeldet zu bleiben. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!