2016-08-09 3 views
3

MongoDB에서 데이터를 가져 오는 Node/Express로 백엔드 API를 구축하고 있습니다. 프론트는 React로 쓰여질 것입니다.Node/Express - 클라이언트/서버 간의 안전한 통신을위한 좋은 접근 방법

통신 클라이언트/서버를 보호하고 싶지만 프로세스에 대해 어떻게 생각해야하는지 잘 모릅니다.

passport 또는 JWT에 대한 자습서가 많이 있지만 이는 사용자 인증에 유용합니다.

시간을 기준으로 모든 요청에 ​​대한 토큰을 만드는 것이 좋은 접근 방법인지 아니면 웹 응용 프로그램에 너무 많은지 모르겠다.

하지만 API가 비공개 인 경우에도 쉽게 경로를 찾아 데이터를 스크랩하기 위해 우편 발송자 또는 다른 방법으로 가짜 요청을하는 방법을 알아낼 수 있기 때문에 데이터를 보호하는 것이 내 목표입니다.

+3

준 관련 메모에서 보안, 시도 및 진정한 사용자/사용자뿐 아니라 HTTPS 사용이 첫 번째 단계라고 생각합니다. [LetsEncrypt] (https://letsencrypt.org/)에서 무료 인증서를 얻을 수 있습니다. 세션 인증 메커니즘 또한 XSS, CSRF 등과 같은 일반적인 공격으로부터 보호하기 위해 [OWASP] (https://www.owasp.org/index.php/Main_Page) 사이트의 정보를 읽어 보시기 바랍니다. – mscdex

+0

감사합니다. ! 나는 XSS와 같은 공격을 이미 다룬'helmet'이라는 미들웨어를 활성화 시켰습니다. https://www.npmjs.com/package/helmet 링크를 살펴 보겠습니다. 메르시! 저는 HTTPS를 확실히 사용할 것이며, 개인 웹 사이트에 사용했기 때문에 LetsEncrypt (지금 생각하는 이름은 cerbot입니다)에 대해 알고 있습니다. 하지만 난 여전히 dev에 모드 (로컬 호스트)에있어 그래서 진짜 서버가 될 때 그것을 할 것입니다. 감사. – Ragnar

답변

2

허용되는 표준은 고정 된 API 키를 사용하는 것입니다. 이 정보 평화는 헤더의 각 요청에서 보내는 임의로 생성 된 문자열이어야합니다. 서버가 헤더에 API KEY가 있는지 확인하기 위해 매번 HTTP 요청을 확인해야하며, 그렇다면 API는 환경 변수에 저장된 값 (코드에 API KEY를 저장하지 마십시오)을 확인해야합니다.

API 키가 손상된 경우 쉽게 env 변수를 업데이트 할 수 있으며 다시 사용할 수 있습니다.

이제 누구나 트래픽을 탐지하고 API 키를 볼 수 있기 때문에이 솔루션은 HTTPS 연결 없이는 무의미합니다. 이 경우 암호화 된 연결이 필수입니다.

이 방법은 거의 모든 공개 API가 회사에 의해 사용된다 : 트위터, 페이스 북, Twilio를, 구글 등의 예를 들어

구글은 그들이 당신에게 만료되는 토큰을주고 추가 단계를 가지고 있지만,이 적어도 처음에는 당신의 경우에 과도한 살인이 될 것입니다.

다음 코드는 전체 구현 hear으로 전체 파일을 확인할 수 있습니다

app.use(function(req, res, next) { 

    // 
    // 1. Check if the APIKey is present 
    // 
    if(!req.headers.authorization) 
    { 
     return res.status(400).json(
      { 
       message: "Missing APIKey.", 
       description: "Unable to find the APIKey" 
      } 
     ); 
    } 

    // 
    // 2. Remove Basic from the beginning of the string 
    // 
    let noBasic = req.headers.authorization.replace('Basic ', ''); 

    // 
    // 3. Convert from base64 to string 
    // 
    let b64toString = new Buffer(noBasic, 'base64').toString("utf8"); 

    // 
    // 4. Remove the colon from the end of the string 
    // 
    let userAPIKey = b64toString.replace(':', ''); 

    // 
    // 5. Check if the APIKey matches the one on the server side. 
    // 
    if(userAPIKey != process.env.API_KEY) 
    { 
     return res.status(400).json(
      { 
       message: "APIKey don't match", 
       description: "Make sure what you are sending is what is in your server." 
      } 
     ); 
    } 

    // 
    // -> Go to the next stage 
    // 
    next() 

}); 

API 키 확인 내 구현의 예입니다.

+0

감사합니다. 지금은 정말 분명합니다. 단지 2 개의 질문. 1) HTTPS 클라이언트/서버 측 (서버 측의 certificat 제외)을 처리하기 위해 특정 설정을해야합니까? nginx를 설치해야합니까? 2) env.API_KEY를 어떻게 관리합니까? 예를 들어,'export EDITOR = emacs'를 설정하는 것처럼 시스템의 env 변수일까요? 또한 클라이언트 측을 어떻게 관리합니까? 같은 코드이지만 역순으로 (문자열을 보내기 전에 인코딩 하시겠습니까?). 감사합니다 – Ragnar

+0

많은 질문 :) 코멘트 섹션은 제한된 숯을 가지고 있기 때문에, 나는 분리 된 코멘트로 각 질문에 대답 할 것입니다. –

+0

** HTTPS ** : 여러 가지 방법이 있으며, 모두 앱을 호스팅 할 위치에 따라 다릅니다. 당신이 Heroku에서 호스트한다면, 당신은 당신 편에서 아무것도 할 필요가 없습니다, 당신은 그들 편에서 SSL을 가능하게합니다. 따라서 당신은 어떻게해야할까요? e- 메일을 직접 쓴다면 내 기사에서 SSL을 추가하는 방법을 알아볼 수 있습니다. https://github.com/davidgatti/IoT-Raw-Sockets-Examples/tree/master/Templates/NodeJS/tls. 당신에게 의존하는 다른 것 : –

1

방금 ​​내 승인 부분을 마치면서 AngularJS 응용 프로그램입니다. 대답은 이며 JWTPassport입니다. 데이터/API를 보호하려면 위대한 기술을 사용해야합니다.

JWT 라이브러리를 사용하는 경우 승인을 위해 http 헤드를 보유하는 데 도움이됩니다.

내가 사용하는 코드의 일부는 :

var jwt = require('express-jwt'); 

var auth = jwt({ 
    secret: config.jwt.secret, 
    userProperty: 'payload' 
}); 

app.use('/api/secret', auth, apiSecretRoutes); 

login.js

module.exports.login = function (req, res) { 
    if (!req.body.username || !req.body.password) { 
     return tools.sendJSONresponse(res, 400, { 
      message: 'All fields required!' 
     }); 
    } 

    passport.authenticate('local', function (err, user, info) { 
     var token; 
     if (err) { 
      return tools.sendJSONresponse(res, 404, err); 
     } 

     if (user) { 
      token = user.generateJwt(); 
      return tools.sendJSONresponse(res, 200, { 
       ok: true, 
       message: 'welcome ' + user.name, 
       token: token 
      }); 
     } else { 
      return tools.sendJSONresponse(res, 400, info); 
     } 
    })(req, res); 
}; 

사용자 app.js.JS

userSchema.methods.generateJwt = function() { 
    var expiryDays = 1; 
    var expiry = new Date(); 
    expiry.setDate(expiry.getDate() + expiryDays); 

    return jwt.sign({ 
     _id: this._id, 
     username: this.username, 
     name: this.name, 
     exp: parseInt(expiry.getTime()/1000) 
    }, config.jwt.secret); 
}; 

더 참고 문헌 :

+1

고맙습니다. 하지만 사용자 이름과 비밀번호로 사용자 인증을받을 필요는 없습니다. 요청과 데이터를 보호하고자하는 내부 API입니다. 사용자가 내 앱 사용을 추적하거나 앱 일부에 대한 액세스를 거부하도록 승인하는 방법은 없습니다.조만간 이런 종류의 승인을 사용할 방법이 필요하기 때문에 고맙습니다.) – Ragnar

관련 문제