プロジェクト1-Auth


呑呑呑項目1-Auth


📕Auth


なぜAuth Routeを作成するのですか?
あるサイトに行くと言ったとき、ログインしたユーザーだけが使用できます.
他のページは誰でも使えるという違いがあります
これを検証するためにAuth機能を作成した.
どのように実施するか説明します.
現在、トークンはサーバのuser情報に格納されています.
クライアントのクッキーにも格納
ユーザーがAサイトからBサイトに移動した場合
このユーザがBサイトの権限を持っているかどうか
クライアント上のCookieをサーバに送信して確認する
Cookie内のトークンは符号化状態にあり,サーバが受信したトークンを復号する.
前の記事では、「secretToken」を付けるとuseridが現れるとのこと.
では、そのuseridを使用してそのuseridのDBにタグがあれば、認証が可能です.
順番に説明すると.
  • クッキーに格納トークンをサーバにインポートして復号する
  • .
  • が復号すると、ユーザID
  • が現れる.
  • のユーザIDでデータベース内のユーザを検索し、Cookieから受信トークン
  • があるか否かを判定する.
    こうする

    📘作成


    私たちが今までルータを作成したとき、このように書いたlogin、signupです.
    後でルータが多くなって、どれと関係がある情報を混同するかもしれません
    だから今まで私たちが作成したルータはユーザーに関連するルータです.
    追加/api/users
    次にauthというミドルウェアを使用してミドルウェアフォルダを作成します
    以降のフォルダでauth.jsという名前のファイルを作成し、次のコードを書きます.
    let auth = (req, res, next) => {
        //인증 처리 하는곳
    }
    
    module.exports = { auth }
    そしてindex上部
    const { auth } = require('./middleware/auth')
    追加が必要
    今は秋jsファイルでの認証

    クライアントからCookieをインポート


    前回使ったクッキーパイでいいです.
    クッキーを入れる時にx authの名前で入れる
    let token = req.cookies.x_auth
    こうしてクッキーからコインを出しました

    トークン解読


    プレイヤーモデルが必要で、プレイヤーモデルを追加させます
    const { User } = require('../models/User')
    トークンを作成する方法はuserです.jsで作成したように
    トークンで検索する方法もuserです.jsで作成するには
    userSchema.statics.findByToken = function ( token, cb ){
       let user = this
    
       jwt.verify(token, 'secretToken', function(err, decoded){
           //userid를 이용해서 확인하기
       })
    }
    jwt.verifyは基本的にjwtが提供する方法です
    サイトに詳しい説明があります
    簡単に言えば、トークンの作成方法について説明しましたが、言い換えれば
    userid+文字列->タグ
    だからverifyでタグを入れて、私たちが指定した文字列を入れた後に
    コールバック関数が間違っている場合、エラーは、正しい場合、復号値を返す方法です.

    useridを使用してユーザーを検索および検証する


    復号後の値で現在のdbのuserで検索する方法
    userSchema.statics.findByToken = function ( token, cb ){
        let user = this
    
        jwt.verify(token, 'secretToken', function(err, decoded){
            user.findOne({ "_id": decoded, "token": token }, function (err, user){
                if(err) return cb(err)
                cb(null, user)
            })
        })
    }
    ユーザーでfindOneというモンゴルdbメソッドを使用してユーザーを検索
    前回とあまり差がないので、理解できるはずです
    こうやって仕上げたらauthjsに行って使います
    const { User } = require('../models/User')
    
    let auth = (req, res, next) => {
        let token = req.cookies.x_auth
    
        User.findByToken(token, (err, user) => {
            if(err) throw err
            if(!user) return res.json({ isAuth: false, error: true })
            
            req.token = token
            req.user = user
            next()
        })
    }
    
    module.exports = { auth }
    findByTokenメソッドの使用
    next()を入れる原因はミドルウェアで、移行がなければ、ずっと閉じ込められています
    index.jsのreq.token, req.ユーザー情報を受信可能
    app.get('api/users/auth', auth, (req, res) => {
      //미들웨어를 통과해 여기까지 왔다는 것은 Auth가 true 라는 의미
      
    })
    ここに来たのはAuthがtrueだという意味です
    クライアントにこの点を示すコードを追加しましょう.
    あなたにユーザー情報を送ります.
    ただし、ロールが0の場合は通常のユーザーです.
    ゼロ以外の数があれば管理者扱い
    app.get('/api/users/auth', auth, (req, res) => {
      //미들웨어를 통과해 여기까지 왔다는 것은 Auth가 true 라는 의미
      res.status(200).json({
        _id: req.user._id,
        isAdmin: req.user.role === 0 ? false : true,
        isAuth: true,
        email: req.user.email,
        name: req.user.name,
        role: req.user.role,
        image: req.user.image
      })
    })
    こうしてコードを作った
    次にPostmanで確認します

    こんなによく見える

    📗コード#コード#


    auth.js
    const { User } = require('../models/User')
    
    let auth = (req, res, next) => {
        let token = req.cookies.x_auth
    
        User.findByToken(token, (err, user) => {
            if(err) throw err
            if(!user) return res.json({ isAuth: false, error: true })
            
            req.token = token
            req.user = user
            next()
        })
    }
    
    module.exports = { auth }
    user.js
    const mongoose = require('mongoose')
    const bcrypt = require('bcrypt')
    const saltRounds = 10
    const jwt = require('jsonwebtoken')
    
    const userSchema = mongoose.Schema({
        name: {
            type: String,
            maxlength: 50
        },
        email: {
            type: String,
            trim: true,
            unique: 1
        },
        password: {
            type: String,
            minlength: 5
        },
        role: {
            type: Number,
            default: 0
        },
        image: String,
        token: {
            type: String
        },
        tokenExp:{
            type: Number
        }
    })
    
    userSchema.pre('save', function(next){
        let user = this;
    
        if (user.isModified('password')){
            bcrypt.genSalt(saltRounds, function (err, salt) {
                if(err) return next(err)
                bcrypt.hash(user.password, salt, function (err, hash){
                    if(err) return next(err)
                    user.password = hash
                    next()
                })
            })
        } else {
            next()
        }
    })
    
    userSchema.methods.comparePassword = function(plainPassword, cb) {
        bcrypt.compare(plainPassword, this.password, function(err, isMatch) {
            if(err) return cb(err)
            cb(null, isMatch)
        })
    }
    
    userSchema.methods.generateToken = function(cb){
        let user = this
        let token = jwt.sign(user._id.toHexString(), 'secretToken');
    
        user.token = token
        user.save(function(err, user){
            if(err) return cb(err)
            cb(null, user)
        })
    }
    
    userSchema.statics.findByToken = function ( token, cb ){
        let user = this
    
        jwt.verify(token, 'secretToken', function(err, decoded){
            user.findOne({ "_id": decoded, "token": token }, function (err, user){
                if(err) return cb(err)
                cb(null, user)
            })
        })
    }
    
    const User = mongoose.model('User', userSchema)
    
    module.exports = { User }
    index.js
    const express = require('express')
    const app = express()
    const port = 3000
    const mongoose = require('mongoose')
    const bodyParser = require('body-parser')
    const config = require('./config/key')
    const cookieParser = require('cookie-parser')
    const { auth } = require('./middleware/auth')
    const { User } = require("./models/User")
    
    
    app.use(bodyParser.urlencoded({extended: true}))
    app.use(bodyParser.json())
    app.use(cookieParser())
    
    mongoose.connect(config.mongoURI
    ).then( () => console.log('MongoDB Connected'))
     .catch(err => console.log(err))
    
    app.get('/', (req, res) => {
      res.send('Hello World! BooKi')
    })
    
    app.post('/api/users/signup', (req, res) => {
      //회원 가입 할 때 작성한 정보들을 가져와 DB에 넣어준다
      const user = new User(req.body)
    
      user.save((err, userInfo) => {
        if (err) return res.json({ success: false, err})
        return res.status(200).json({
          success: true
        })
      })
    })
    
    app.post('/api/users/login', (req, res) => {
      User.findOne({ email: req.body.email }, (err, user) => {
        if(!user) {
          return res.json({
            loginSuccess: false,
            message: "해당 이메일에 해당하는 유저가 없습니다."
          })
        }
    
        user.comparePassword(req.body.password, (err, isMatch) => {
          if(!isMatch){
            return res.json({
              loginSuccess: false,
              message: "비밀번호가 틀렸습니다."
            })
          }
          user.generateToken((err, user) => {
            if(err) {
              return res.status(400).send(err)
            }
                    
            res.cookie("x_auth", user.token)
            .status(200)
            .json({
              loginSuccess: true,
              userId: user._id
            })
          })
        })
      })
    })
    
    app.get('/api/users/auth', auth, (req, res) => {
      //미들웨어를 통과해 여기까지 왔다는 것은 Auth가 true 라는 의미
      res.status(200).json({
        _id: req.user._id,
        isAdmin: req.user.role === 0 ? false : true,
        isAuth: true,
        email: req.user.email,
        name: req.user.name,
        role: req.user.role,
        image: req.user.image
      })
    })
    
    app.listen(port, () => {
      console.log(`http://localhost:${port}/`)
    })