Node.js认证与URL短链接融合应用开发求助
Node.js 登录认证 + URL短链接整合实现方案
你需要的是整合登录认证与URL短链接功能的Node.js应用,启动后先进入登录页,认证通过后才能使用短链接功能。以下是修复并整合后的完整代码,以及关键修改说明:
完整代码
if (process.env.NODE_ENV !== "production") { require("dotenv").config(); } const express = require("express"); const app = express(); const bcrypt = require("bcrypt"); const passport = require("passport"); const initializePassport = require("./passport"); const flash = require("express-flash"); const session = require("express-session"); const mongoose = require("mongoose"); const ShortUrl = require("./models/shortUrl"); // 连接MongoDB mongoose.connect("mongodb://localhost/urlShortener", { useNewUrlParser: true, useUnifiedTopology: true, }); const users = []; // 初始化Passport initializePassport( passport, (email) => users.find((user) => user.email === email), (id) => users.find((user) => user.id === id) ); // 中间件配置 app.set("view engine", "ejs"); app.use(express.urlencoded({ extended: false })); app.use(flash()); app.use( session({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false, }) ); app.use(passport.initialize()); app.use(passport.session()); // 登录验证中间件:未登录用户无法访问受保护路由 function checkAuthenticated(req, res, next) { if (req.isAuthenticated()) { return next(); } res.redirect("/login"); } // 路由配置 // 根路由重定向到登录页,启动后直接加载登录 app.get("/", (req, res) => { res.redirect("/login"); }); // 登录页 app.get("/login", (req, res) => { res.render("login.ejs"); }); // 注册页 app.get("/register", (req, res) => { res.render("register.ejs"); }); // 登录提交 app.post( "/login", passport.authenticate("local", { successRedirect: "/index", failureRedirect: "/login", failureFlash: true, }) ); // 注册提交 app.post("/register", async (req, res) => { try { const hashedPassword = await bcrypt.hash(req.body.password, 10); users.push({ id: Date.now().toString(), name: req.body.name, email: req.body.email, password: hashedPassword, }); res.redirect("/login"); } catch (e) { console.log(e); res.redirect("/register"); } }); // 登出(可选添加) app.post("/logout", (req, res) => { req.logout((err) => { if (err) return next(err); res.redirect("/login"); }); }); // 受保护的首页(URL短链接功能页) app.get("/index", checkAuthenticated, async (req, res) => { const shortUrls = await ShortUrl.find(); res.render("index", { shortUrls: shortUrls, user: req.user }); }); // 创建短链接 app.post("/shortUrls", checkAuthenticated, async (req, res) => { await ShortUrl.create({ full: req.body.fullUrl }); res.redirect("/index"); }); // 短链接跳转 + 访问计数 app.get("/:shortUrl", async (req, res) => { const shortUrl = await ShortUrl.findOne({ short: req.params.shortUrl }); if (shortUrl == null) return res.sendStatus(404); shortUrl.clicks++; await shortUrl.save(); res.redirect(shortUrl.full); }); app.listen(3000, () => { console.log("服务器运行在http://localhost:3000"); });
关键修改说明
- 登录跳转修复:把原代码中登录成功跳转的
/index.ejs改为/index,路由对应控制器而非直接访问模板文件 - 添加登录保护中间件:新增
checkAuthenticated函数,确保未登录用户无法访问首页和短链接创建接口 - 根路由重定向:设置
/路由直接跳转到登录页,满足启动后先加载登录的需求 - 修复短链接计数:原代码点击短链接未统计访问量,添加
shortUrl.clicks++并执行保存操作 - 优化依赖顺序:调整mongoose连接和模块引入位置,避免加载顺序导致的错误
- 移除重复配置:删除重复的
app.use(express.urlencoded({ extended: false })) - 新增登出路由:补充登出功能,完善完整的认证流程
配套模板与模型文件
- login.ejs(登录页)
<!DOCTYPE html> <html> <head> <title>登录</title> </head> <body> <h1>登录</h1> <% if (messages.error) { %> <p style="color: red;"><%= messages.error %></p> <% } %> <form method="POST" action="/login"> <div> <label>邮箱:</label> <input type="email" name="email" required> </div> <div> <label>密码:</label> <input type="password" name="password" required> </div> <button type="submit">登录</button> </form> <p>还没有账号?<a href="/register">注册</a></p> </body> </html>
- register.ejs(注册页)
<!DOCTYPE html> <html> <head> <title>注册</title> </head> <body> <h1>注册</h1> <form method="POST" action="/register"> <div> <label>姓名:</label> <input type="text" name="name" required> </div> <div> <label>邮箱:</label> <input type="email" name="email" required> </div> <div> <label>密码:</label> <input type="password" name="password" required> </div> <button type="submit">注册</button> </form> <p>已有账号?<a href="/login">登录</a></p> </body> </html>
- index.ejs(短链接功能页)
<!DOCTYPE html> <html> <head> <title>URL短链接工具</title> </head> <body> <h1>欢迎, <%= user.name %>!</h1> <form method="POST" action="/shortUrls"> <div> <label>输入长链接:</label> <input type="url" name="fullUrl" placeholder="https://example.com" required> <button type="submit">生成短链接</button> </div> </form> <h2>已生成的短链接</h2> <table> <thead> <tr> <th>长链接</th> <th>短链接</th> <th>访问次数</th> </tr> </thead> <tbody> <% shortUrls.forEach(url => { %> <tr> <td><a href="<%= url.full %>"><%= url.full %></a></td> <td><a href="<%= url.short %>"><%= req.protocol + '://' + req.get('host') + '/' + url.short %></a></td> <td><%= url.clicks %></td> </tr> <% }) %> </tbody> </table> <form method="POST" action="/logout"> <button type="submit">登出</button> </form> </body> </html>
- models/shortUrl.js(MongoDB模型)
const mongoose = require('mongoose'); const shortId = require('shortid'); const shortUrlSchema = new mongoose.Schema({ full: { type: String, required: true }, short: { type: String, required: true, default: shortId.generate }, clicks: { type: Number, required: true, default: 0 } }); module.exports = mongoose.model('ShortUrl', shortUrlSchema);
依赖安装
执行以下命令安装所有所需依赖包:
npm install express ejs bcrypt passport passport-local express-flash express-session mongoose shortid dotenv
内容的提问来源于stack exchange,提问作者moonstar
相关产品推荐
相关产品推荐

