2017-12-20 2 views
1

오늘은 응용 프로그램에서 올바르게 설정하는 방법을 알아 내려고 passport-jwt를 사용해 보았습니다. 사용자 등록 및 jwt 토큰 저장에 문제가 없었지만 여권을 사용하고 있다고 생각하지 않습니다. 이제 사용자 로그인을 시도하고 있는데 항상 오류 Error: Failed to serialize user into session가 표시됩니다. 나는 아래 기사의 숫자에서 볼 수있다 :Passport, Unified Serialization, 401 Error

passport.serializeUser((user, done) => { 
    done(null, user.id); 
}); 

passport.deserializeUser((id, done) => { 
    User.findById(id, (err, user) => { 
     done(err, user); 
    }); 
}); 

그러나 나는 어떤 예 또는이 어디에 사용 설명 여권 문서의도 구성 부분을 찾을 수 없습니다. 내 문제의 근원 일 수는 있지만 확실하지 않습니다. 혼란 스러울 수있는 여권의 특징 중 하나는 JWT 추출기입니다. 나는 여권을 jwt 토큰으로 바꾸고 mongo 데이터베이스에 저장하기 만하면되는데, 왜 내가 필요로하는 것일까? jsonwebtoken을 사용하고 필요에 따라 문자열을 해시/해해하지 않고 cookie-parser을 사용하여 Passport와 같은 것을 사용하는 대신 내 세션을 만드는 것이 더 쉽지 않습니까? 나는 또한 나머지 호출에서 passport.authenicate()를 사용하려고 시도했지만 401이 반환됩니다. 실패한 시도가 로그인 호출 아래에 주석 처리 된 것을 볼 수 있습니다.

제발 도와주세요, 나는 훨씬 덜 강력한 것보다 복잡한 여권을 찾고있는 유일한 사람인 것처럼 느낍니다. 그러나 나는 그것을 밖으로 분류하는 데 정말로 전념하고 있습니다!

import express from 'express'; 
import path from 'path'; 
import bodyParser from 'body-parser'; 
import connection from './database'; 
import jwt from 'jsonwebtoken'; 
import cors from 'cors'; 
import crypto from 'crypto'; 
import passport from "passport"; 
import passportJWT from "passport-jwt"; 
const JwtStrategy = passportJWT.Strategy; 
const ExtractJwt = passportJWT.ExtractJwt; 
import { User } from './schema'; 
import { read } from 'fs'; 
const app = express(); 
const corsOptions = { 
    origin: '*', 
    optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204 
} 
app.use(cors(corsOptions)); 
app.use(passport.initialize()); 
app.use(passport.session()); 

const jwtOptions = { 
    jwtFromRequest: ExtractJwt.fromBodyField('Password'), 
    secretOrKey: 'secretKey', 
    jsonWebTokenOptions: { expiresIn: 172800 } 
} 

passport.use(new JwtStrategy(jwtOptions, (jwt_payload, done) => { 
    User.findOne({ password: jwt_payload.sub }, (err, user) => { 
    user ? done(null, user) : done(null, false); 
    }); 
})); 

passport.serializeUser((user, done) => { 
    done(null, user.id); 
}); 

passport.deserializeUser((id, done) => { 
    User.findById(id, (err, user) => { 
     done(err, user); 
    }); 
}); 

app.use(bodyParser.urlencoded({ extended: true })); 
app.use(bodyParser.json()); 

app.use(express.static(path.join(__dirname, 'build'))); 

app.get('/*', (req, res) => { 
    res.sendFile(path.join(__dirname, 'build', 'index.html')); 
}); 

app.post('/test', (req, res) => { 
    console.log('Success'); 
    console.log(req.body); 
    res.json(req.body); 
}); 

app.post('/register', async (req, res) => { 
    if (req.body.FirstName 
    && req.body.LastName 
    && req.body.Email 
    && req.body.Password 
) { 
    const token = await jwt.sign(
     { Password: req.body.Password }, 
     jwtOptions.secretOrKey, 
     { expiresIn: '48h' } 
    ); 
    const CreatedAt = await Date.now(); 
    const newUser = await new User({ 
     FirstName: req.body.FirstName, 
     LastName: req.body.LastName, 
     Email: req.body.Email, 
     Password: token, 

    }); 
    await newUser.save(err => { 
     err ? console.log(err) : res.json(newUser); 
    }); 
    } 
    throw new('error'); 
}); 

// app.post('/login', passport.authenticate('jwt', { session: false }), 
// (req, res) => { 
//  console.log(req.user) 
// if (req.body.Email && req.body.Password) { 
//  User.findOne({ Email: req.body.Email }, (err, user) => { 
//  if (err) return console.log(err); 
//  console.log(user); 
//  return user; 
//  }).then((res) => { 
//  jwt.verify(res.Password, jwtOptions.secretOrKey, (err, decoded) => { 
//   err ? console.log(err) : 
//   req.login(decoded, (err) => { 
//   // if (err) { return next(err); }; 
//   if (err) { 
//    console.log(err) 
//   } else { 
//    console.log(decoded) 
//   } 
//   }); 
//  }); 
//  }).catch(err => console.log('Failed ', err)); 
// } else { 
//  console.log(req.body); 
// } 
// }); 

app.post('/login', (req, res) => { 
    if (req.body.Email && req.body.Password) { 
    User.findOne({ Email: req.body.Email }, (err, user) => { 
     if (err) return console.log(err); 
     console.log(user); 
     return user; 
    }).then((res) => { 
     // res.password returns the jwt string successfully 
     jwt.verify(res.Password, jwtOptions.secretOrKey, (err, decoded) => { 
     err ? console.log(err) : 
     req.login(decoded, (err) => { 
      // if (err) { return next(err); }; 
      if (err) { 
      console.log(err) // always returns the error posted above 
      } else { 
      console.log(decoded) 
      } 
     }); 
     }); 
    }).catch(err => console.log('Failed ', err)); 
    } else { 
    console.log(req.body); 
    } 
}); 

app.listen(9000,() => { 
    console.log(`Listening on port 9000`); 
}); 

사용자 정의 추출기는 시도는 @OrthoHomeDefense에 의해 포스트를 바탕으로

const customExtractor = req => { 
    User.findOne({ Email: req.body.Email }, '_id', (err, user) => { 
    const token = jwt.sign(
     { id: user }, 
     'secretKey', 
     { expiresIn: '48h' } 
    ); 
    return token; 
    }); 

내가 만든 다음 성공적으로 클라이언트에 JWT 토큰을 보내

app.post("/login", (req, res) => { 
    if (req.body.Email && req.body.Password) { 
    User.findOne({ Email: req.body.Email }, (err, user) => { 
     if(user.Password === req.body.Password) { 
     console.log() 
     var token = jwt.sign(JSON.stringify(user), jwtOptions.secretOrKey); 
     res.json({token: token}); 
     } else { 
     console.log(err); 
     res.status(401).json({message:"Passwords did not match."}); 
     } 
    }); 
    } else { 
    res.status(401).json({message:"Please provide an email and a password."}); 
    } 
}); 
+0

본 적이 있습니까? https://jonathanmh.com/express-passport-json-web-token-jwt-authentication-beginners/ –

+0

@OrthoHomeDefense \t 나는 그것을 읽었으며, 내가 Passport JWT 전략 섹션에 갇혀있는 것 같습니다. 401을받는 중입니다. 이해가 안되는 부분은 추출자 자체입니다. 규정 된 추출기 위치에서 jwt를받는 이유는 무엇입니까?암호가 한 번 해시 된 문자열이 아닌가? 이 경우 추출기 위치가 아닌 데이터베이스에서 jwt를 수신하지 못합니까? 내가 틀린 것이 틀림 없다고 말하는 것을 안다. 그러나 나는 어떻게 알아낼 수없는 것일까? – Brandon

+0

클라이언트 측에서 요청을 호출하면 어떻게 보이는지 보여 줄 수 있습니까? –

답변

0

당신은 jwt.verify(...)를 호출하고 그것은 토큰을 확인하는 것입니다. 로그인시 토큰을 확인할 필요가 없습니다. 로그인시 생성해야합니다.

이 단계를 통해 /login 단계로 진행하고 실행 방법을 알려주십시오.

app.post("/login", function(req, res) { 
     if(req.body.name && req.body.password){ 
     var name = req.body.name; 
     var password = req.body.password; 
     } 
     // usually this would be a database call: 
     //find user by username and password 
     if(!user){ 
     res.status(401).json({message:"no such user found"}); 
     } 

     if(verify user is correct) { 

     //token is created here 
     var token = jwt.sign(payload, jwtOptions.secretOrKey); 
     //here is the response 
     res.json({message: "ok", token: token}); 
     } else { 
     error 
     res.status(401).json({message:"passwords did not match"}); 
     } 
    }); 
+0

로그인을 위해 위의 솔루션과 관련하여 내 새 코드를 내 질문의 맨 아래에 게시했습니다. 서버에 대한 모든 호출과 함께 올바르게 이해한다면,'header : { 'Authorization': jwtToken}처럼'passport.authenticate()'가 사용될 때마다 제공된 jwt 토큰을 서버에 보내야 할 것입니다. '? 나는 상태에서 토큰을 저장하는 것은 매우 안전하지 않다고 생각하지만 전화를 걸지 않을 때 어딘가에 보관해야합니다. – Brandon

+0

네, 맞아요. 저장 위치는 토큰이 만료되는 시점과 앱의 요구에 따라 다릅니다. 당신은 DB에 저장할 수 있습니다. 나는 그 문제를 보지 못합니다. 나는 여권에 대한 문서를 철저히 체크 아웃하지는 않았지만, 아마 당신을 위해 그 단계 중 일부를 할 수 있습니다. 그것이 어떻게 작동하는지 알려주십시오. –

+0

고마워요! jwt 토큰을 사용하는 데 문제가 없지만 불행히도'app.post ('/ test', passport.authenticate ('jwt', {session : false}), (req, res) => {console (http : // localhost : 9000/login ', {헤더 : {'인증 ': 토큰}, 데이터 : {테스트 :'테스트 ' , Token : token}}'서버에서 보낸 내용에 대해 추출기 'fromAuthHeaderAsBearerToken() fromHeader ("authorization") fromBodyField ('Token ')을 시도했지만 그 중 아무 것도 차이를 만들지 않습니다. 문서는 상관 없지만 알면 좋다. – Brandon

1

은 우선 해제, @OrthoHomeDefense 내가 무엇을 필요로하는 것은 그것을 설정 어디 여권을 사용하는 초기에 따라야하기위한로 혼란 스러웠로 로그인을 설정에 대한 내 최초의 문제를 해결했다.

다음은 클라이언트에서 서버로의 나의 호출입니다.

export const test = token => { 
    console.log(token) 
    return dispatch => { 
    axios.post('http://localhost:9000/test', 
    { 
     headers: {'authorization': token}, 
     data: {test: 'test', Token: token} 
    } 
).then((res) => { 
     console.log(res.data); 
    }) 
    .catch((error) => { console.log(error); }); 
    } 
} 

다음은 내가 서버 측에서 수행 한 관련 테스트입니다.

const customExtractor = req => { 
    let token = req.body.headers.authorization; 
    console.log(token); 
    return token; 
} 

const jwtOptions = { 
    jwtFromRequest: customExtractor, 
    secretOrKey: 'secretKey', 
} 

passport.use(new JwtStrategy(jwtOptions, (jwt_payload, done) => { 
    console.log('Success', jwt_payload); 
    User.findOne({id: jwt_payload.sub}, (err, user) => { 
    if (err) return done(err, false); 
    if (user) { 
     return done(null, user); 
    } else { 
     return done(null, false); 
    } 
    }); 
})); 

나는 아래의 추출기를 매번 404 번의 수신을 시도 했으므로 위의 매우 간단한 추출기를 만들었습니다. 토큰을 쿠키 또는 유사한 것으로 저장하면 직접 추출기에서 해당하는대로 편집하십시오.

jwtFromRequest: ExtractJwt.fromBodyField('Token'), jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), jwtFromRequest: ExtractJwt.fromHeader("authorization"),

+0

솔루션을 찾았 기쁘다. –

관련 문제