Node.jsがゼロからウェブserverブログプロジェクトを開発する[登録]


web serverブログプロジェクト
  • Node.jsがゼロからウェブserverブログプロジェクトを開発します。
  • Node.jsがゼロからウェブserverブログプロジェクトを開発しました。
  • Node.jsはゼロからウェブserverブログプロジェクトを開発します。
  • Node.jsがゼロからウェブserverブログプロジェクトを開発しました。
  • Node.jsがゼロからウェブserverブログプロジェクトを開発しました。
  • Node.jsがゼロからウェブserverブログプロジェクトを開発しました。
  • Node.jsがゼロからウェブserverブログプロジェクトを開発しました。
  • Node.jsがゼロからウェブserverブログプロジェクトを開発しました。
  • Node.jsがゼロからウェブserverブログプロジェクトを開発します。
    記事の目次
  • クッキー
  • クッキーは何ですか?
  • JavaScriptはcookieを操作して、ブラウザーの中でcookie
  • を調べます。
  • クライアントはクッキーを調べ、3つの方法
  • JavaScriptの表示/cookieの変更(制限あり)
  • server端はcookieを操作して、登録検証を実現します。
  • クッキーを制限する
  • セッション
  • セッションはredis
  • に預け入れられます。
  • と先端連結
  • クッキー
  • クッキーは何ですか?
  • は、ブラウザの一部の文字列(最大5 kb)
  • に格納されている。
  • ドメインをまたぐ
  • を共有しません。
  • フォーマットはk 1=v 1のようです。k 2=v 2;k 3=v 3;したがって、構造化データ
  • を記憶することができる。
  • http要求を送信するたびに、要求ドメインのcookieをserver
  • に送信する。
  • serverはcookieを変更してブラウザ
  • に戻すことができます。
  • ブラウザでは、JavaScriptによりクッキーを変更することもできます。
  • JavaScriptはcookieを操作して、ブラウザーの中でcookie
  • を調べます。
  • クライアントはクッキーを調べ、3つの方法
  • Network->Reques Headers->Cookie
  • Application->Cookie
  • document.cookie
  • JavaScript表示/cookieの変更(制限あり)
  • document.cookie = 'foo=bar;'はクッキーを増やすだけで、
  • を削除できません。
  • server端はcookieを操作して、登録検証を実現します。
    app.js
      //    cookie
      req.cookie = {}
      const cookieStr = req.headers.cookie || '' // k1=v1; k2=v2; k3=v3
      cookieStr.split(';').forEach(item => {
        if (!item) {
          return
        }
        const arr = item.split('=')
        const key = arr[0]
        const val = arr[1]
        req.cookie[key] = val
      })
      
      console.log('req.cookie is: ', req.cookie) 
      //       document.cookie = 'username: zhangsan;'
      // req.cookie is:  { username: 'zhangsan' }
    
    router/user.js
     //   
      if (method === 'GET' && path === '/api/user/login') {
        // const {
        //   username,
        //   password
        // } = req.body
    
        const { username, password } = req.query
        const result = login(username, password)
    
        // if (result) {
        //   return new SuccessModel(result)
        // } else {
        //   return new ErrorModel('    ')
        // }
    
        return result.then(data => {
          if (data.username) {
    
            //    cookie
            res.setHeader('Set-Cookie', `username=${data.username}; path=/`)
    
            return new SuccessModel()
          }
          return new ErrorModel('    ')
        })
      }
    
      //       
      if (method === 'GET' && req.path === '/api/user/login-test') {
        if (req.cookie.username) {
          return Promise.resolve(
            new SuccessModel({
              username: req.cookie.username
            })
          )
        }
        return Promise.reject(
          new ErrorModel('    ')
        )
      }
    
    クッキーを制限する
    クライアントがログインに成功したら、cookieを削除します。cookie(username=lisi)->cookieを追加します。張三のアカウントで操作する李四アカウントrouter/user.jsが見つかります。
    const {
      login
    } = require('../controller/user')
    const { SuccessModel, ErrorModel } = require('../model/resModel')
    
    //    cookie      
    const getCookieExpires = () => {
      const d = new Date()
      d.setTime(d.getTime() + (24 * 60 * 60 * 1000))
      return d.toGMTString() // Mon, 08 Jul 2019 05:27:33 GMT
    }
    
    handleUserRouter = (req, res) => {
      const {
        method,
        path
      } = req
    
      //   
      if (method === 'GET' && path === '/api/user/login') {
        // const {
        //   username,
        //   password
        // } = req.body
    
        const { username, password } = req.query
        const result = login(username, password)
    
        // if (result) {
        //   return new SuccessModel(result)
        // } else {
        //   return new ErrorModel('    ')
        // }
    
        return result.then(data => {
          if (data.username) {
    
            //    cookie
            res.setHeader('Set-Cookie', `username=${data.username}; path=/; httpOnly; expires=${getCookieExpires()}`)
            // path=/        
            // httpOnly         
            // expires     
    
            return new SuccessModel()
          }
          return new ErrorModel('    ')
        })
      }
    
      //       
      if (method === 'GET' && req.path === '/api/user/login-test') {
        if (req.cookie.username) {
          return Promise.resolve(
            new SuccessModel({
              username: req.cookie.username
            })
          )
        }
        return Promise.reject(
          new ErrorModel('    ')
        )
      }
    }
    
    module.exports = handleUserRouter
    
    セッション
  • 前の段の問題:usernameを暴露することができて、とても危険です。
  • どう解決しますか?cookieにはuseridが格納されています。server端はusername
  • に対応しています。
  • ソリューション:session、つまりsever端末にユーザ情報ap.js
  • を格納する。
    // session   
    const SESSION_DATA = {}
    
    //    cookie      
    const getCookieExpires = () => {
      const d = new Date()
      d.setTime(d.getTime() + (24 * 60 * 60 * 1000))
      return d.toGMTString() // Mon, 08 Jul 2019 05:27:33 GMT
    }
    ...
      //    session
      let needSetCookie = false
      let userId = req.cookie.userid
      if (userId) {
        if(!SESSION_DATA[userId]) {
          SESSION_DATA[userId] = {}
        }
      } else {
        needSetCookie = true
        userId = `${Date.now()}_${Math.random()}`
        SESSION_DATA[userId] = {}
      }
    
      req.session = SESSION_DATA[userId]
      ...
        //    user   
        const userResult = handleUserRouter(req, res)
        if (userResult) {
          userResult.then(userData => {
    
            if (needSetCookie) {
              res.setHeader('Set-Cookie', `userid=${userId}; path=/; httpOnly; expires=${getCookieExpires()}`)
            }
    
            res.end(
              JSON.stringify(userData)
            )
          })
          return
        }
    
    router/user.js
        return result.then(data => {
          if (data.username) {
    
            //    cookie
            res.setHeader('Set-Cookie', `userid=${data.userId}; path=/; httpOnly; expires=${getCookieExpires()}`)
            // path=/        
            // httpOnly         
            // expires     
            
            //    session
            req.session.username = data.username
            req.session.realname = data.realname
            console.log('req.session is : ', req.session)        
    
            return new SuccessModel(req.session)
          }
          return new ErrorModel('    ')
        })
      }
    
      //       
      if (method === 'GET' && req.path === '/api/user/login-test') {
        if (req.session.username) {
          return Promise.resolve(
            new SuccessModel({
              username: req.session
            })
          )
        }
        return Promise.reject(
          new ErrorModel('    ')
        )
      }
    
    セッション預け入れredis
  • cnpm i redis -S
  • conf/db.js
  • const env = process.env.NODE_ENV //     
    
    //   
    let MYSQL_CONF
    let REDIS_CONF
    
    if (env === 'dev') {
      // MySQL
      MYSQL_CONF = {
        host: 'localhost',
        user: 'root',
        password: 'root',
        port: '3306',
        database: 'myblog'
      }
    
      // redis
      REDIS_CONF = {
        port: 6379,
        host: '127.0.0.1'
      }
    }
    
    if (env === 'production') {
      MYSQL_CONF = {
        host: 'localhost',
        user: 'root',
        password: 'root',
        port: '3306',
        database: 'myblog'
      }
    
      // redis
      REDIS_CONF = {
        port: 6379,
        host: '127.0.0.1'
      }
    }
    
    module.exports = { MYSQL_CONF, REDIS_CONF }
    
  • 作成db/redis.js
  • const redis = require('redis')
    const { REDIS_CONF } = require('../conf/db.js')
    
    //      
    const redisClient = redis.createClient(REDIS_CONF.port, REDIS_CONF.host)
    redisClient.on('error', err => {
        console.error(err)
    })
    
    function set(key, val) {
        if (typeof val === 'object') {
            val = JSON.stringify(val)
        }
        redisClient.set(key, val, redis.print)
    }
    
    function get(key) {
        const promise = new Promise((resolve, reject) => {
            redisClient.get(key, (err, val) => {
                if (err) {
                    reject(err)
                    return
                }
                if (val == null) {
                    resolve(null)
                    return
                }
    
                try {
                    resolve(
                        JSON.parse(val)
                    )
                } catch (ex) {
                    resolve(val)
                }
            })
        })
        return promise
    }
    
    module.exports = {
        set,
        get
    }
    
  • router/blogs.js
  • const {
      getList,
      getDetail,
      newBlog,
      updateBlog,
      delBlog
    } = require('../controller/blog')
    const { SuccessModel, ErrorModel } = require('../model/resModel')
    
    //          
    const loginCheck = (req) => {
      if (!req.session.username) {
          return Promise.resolve(
              new ErrorModel('    ')
          )
      }
    }
    
    const handleBlogRouter = (req, res) => {
      const method = req.method // GET POST
      const id = req.query.id
    
      //       
      if (method === 'GET' && req.path === '/api/blog/list') {
          let author = req.query.author || ''
          const keyword = req.query.keyword || ''
          // const listData = getList(author, keyword)
          // return new SuccessModel(listData)
    
          if (req.query.isadmin) {
              //      
              const loginCheckResult = loginCheck(req)
              if (loginCheckResult) {
                  //    
                  return loginCheckResult
              }
              //          
              author = req.session.username
          }
    
          const result = getList(author, keyword)
          return result.then(listData => {
              return new SuccessModel(listData)
          })
      }
    
      //       
      if (method === 'GET' && req.path === '/api/blog/detail') {
          // const data = getDetail(id)
          // return new SuccessModel(data)
          const result = getDetail(id)
          return result.then(data => {
              return new SuccessModel(data)
          })
      }
    
      //       
      if (method === 'POST' && req.path === '/api/blog/new') {
          // const data = newBlog(req.body)
          // return new SuccessModel(data)
    
          const loginCheckResult = loginCheck(req)
          if (loginCheckResult) {
              //    
              return loginCheckResult
          }
    
          req.body.author = req.session.username
          const result = newBlog(req.body)
          return result.then(data => {
              return new SuccessModel(data)
          })
      }
    
      //       
      if (method === 'POST' && req.path === '/api/blog/update') {
          const loginCheckResult = loginCheck(req)
          if (loginCheckResult) {
              //    
              return loginCheckResult
          }
    
          const result = updateBlog(id, req.body)
          return result.then(val => {
              if (val) {
                  return new SuccessModel()
              } else {
                  return new ErrorModel('      ')
              }
          })
      }
    
      //       
      if (method === 'POST' && req.path === '/api/blog/del') {
          const loginCheckResult = loginCheck(req)
          if (loginCheckResult) {
              //    
              return loginCheckResult
          }
    
          const author = req.session.username
          const result = delBlog(id, author)
          return result.then(val => {
              if (val) {
                  return new SuccessModel()
              } else {
                  return new ErrorModel('      ')
              }
          })
      }
    }
    
    module.exports = handleBlogRouter
    
  • router/user.js
  • const { login } = require('../controller/user')
    const { SuccessModel, ErrorModel } = require('../model/resModel')
    const { set } = require('../db/redis')
    
    const handleUserRouter = (req, res) => {
        const method = req.method // GET POST
    
        //   
        if (method === 'POST' && req.path === '/api/user/login') {
            const { username, password } = req.body
            // const { username, password } = req.query
            const result = login(username, password)
            return result.then(data => {
                if (data.username) {
                    //    session
                    req.session.username = data.username
                    req.session.realname = data.realname
                    //     redis
                    // console.log(req.session)
                    set(req.sessionId, req.session)
    
                    return new SuccessModel()
                }
                return new ErrorModel('    ')
            })
        }
    }
    
    module.exports = handleUserRouter
    
    
  • と先端連結
  • 登録機能はクッキーに依存しています。ブラウザで
  • を接続しなければなりません。
  • cookieはドメインをまたいで共有しません。フロントエンドとserver端はドメイン
  • と同じでなければなりません。
  • は、nginxを使用してエージェントを行う必要があります。前後のエンドが同じドメイン
  • になります。