Skip to content

Web应用身份认证

认证方案

Session-Cookie认证

javascript
// 服务器端设置Session
app.use(
  session({
    secret: 'your-secret-key',
    resave: false,
    saveUninitialized: false,
    cookie: {
      secure: true,
      httpOnly: true,
      maxAge: 24 * 60 * 60 * 1000 // 24小时
    }
  })
)

// 登录处理
app.post('/login', (req, res) => {
  const { username, password } = req.body
  // 验证用户
  if (validUser) {
    req.session.userId = user.id
    res.json({ success: true })
  }
})

JWT认证

javascript
// JWT配置
const jwt = require('jsonwebtoken')
const SECRET_KEY = 'your-secret-key'

// 生成Token
function generateToken(user) {
  return jwt.sign({ id: user.id, role: user.role }, SECRET_KEY, { expiresIn: '24h' })
}

// 验证Token中间件
const verifyToken = (req, res, next) => {
  const token = req.headers.authorization?.split(' ')[1]
  if (!token) {
    return res.status(401).json({ message: '未提供token' })
  }

  try {
    const decoded = jwt.verify(token, SECRET_KEY)
    req.user = decoded
    next()
  } catch (err) {
    res.status(401).json({ message: 'token无效' })
  }
}

OAuth 2.0认证

javascript
// 使用Passport实现GitHub OAuth认证
const passport = require('passport')
const GitHubStrategy = require('passport-github2').Strategy

passport.use(
  new GitHubStrategy(
    {
      clientID: 'your-client-id',
      clientSecret: 'your-client-secret',
      callbackURL: 'http://localhost:3000/auth/github/callback'
    },
    function (accessToken, refreshToken, profile, done) {
      // 保存用户信息
      User.findOrCreate({ githubId: profile.id }, function (err, user) {
        return done(err, user)
      })
    }
  )
)

安全最佳实践

密码安全

javascript
// 使用bcrypt加密密码
const bcrypt = require('bcrypt')
const saltRounds = 10

// 加密密码
async function hashPassword(password) {
  const salt = await bcrypt.genSalt(saltRounds)
  return bcrypt.hash(password, salt)
}

// 验证密码
async function verifyPassword(password, hash) {
  return bcrypt.compare(password, hash)
}

防止XSS攻击

javascript
// 使用helmet设置安全响应头
const helmet = require('helmet')
app.use(helmet())

// 输入验证
const { body, validationResult } = require('express-validator')

app.post('/api/user', body('username').trim().escape(), body('email').isEmail().normalizeEmail(), (req, res) => {
  const errors = validationResult(req)
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() })
  }
  // 处理请求
})

防止CSRF攻击

javascript
// 使用CSRF令牌
const csrf = require('csurf')
app.use(csrf({ cookie: true }))

// 在表单中添加CSRF令牌
app.get('/form', (req, res) => {
  res.render('form', { csrfToken: req.csrfToken() })
})

权限管理

基于角色的访问控制(RBAC)

javascript
// 角色中间件
const checkRole = (role) => {
  return (req, res, next) => {
    if (!req.user) {
      return res.status(401).json({ message: '未认证' })
    }
    if (req.user.role !== role) {
      return res.status(403).json({ message: '无权限' })
    }
    next()
  }
}

// 使用角色中间件
app.get('/admin', checkRole('admin'), (req, res) => {
  res.json({ message: '管理员页面' })
})

权限粒度控制

javascript
// 资源权限检查
const checkPermission = (resource, action) => {
  return async (req, res, next) => {
    try {
      const hasPermission = await Permission.check({
        userId: req.user.id,
        resource,
        action
      })
      if (!hasPermission) {
        return res.status(403).json({ message: '无权限' })
      }
      next()
    } catch (err) {
      next(err)
    }
  }
}

性能优化

缓存策略

javascript
// Redis缓存用户信息
const Redis = require('ioredis')
const redis = new Redis()

// 缓存用户信息
async function cacheUserInfo(userId, userInfo) {
  await redis.set(`user:${userId}`, JSON.stringify(userInfo), 'EX', 3600)
}

// 获取缓存的用户信息
async function getCachedUserInfo(userId) {
  const cached = await redis.get(`user:${userId}`)
  return cached ? JSON.parse(cached) : null
}

并发控制

javascript
// 使用rate-limiter限制登录请求
const rateLimit = require('express-rate-limit')

const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15分钟
  max: 5, // 限制5次尝试
  message: '登录尝试次数过多,请稍后再试'
})

app.post('/login', loginLimiter, (req, res) => {
  // 登录处理
})

总结

TIP

身份认证是Web应用安全的核心组件,选择合适的认证方案并遵循安全最佳实践至关重要。在实现认证系统时,需要平衡安全性、用户体验和系统性能,同时要考虑到系统的可扩展性和维护性。通过合理使用缓存、并发控制等技术,可以在保证安全性的同时提供良好的用户体验。