node.js에 대한 사용자 인증 라이브러리?


274

node.js에 대한 기존 사용자 인증 라이브러리가 있습니까? 특히 사용자 정의 백엔드 인증 DB를 사용하여 사용자의 비밀번호 인증을 수행하고 해당 사용자를 세션과 연결할 수있는 것을 찾고 있습니다.

인증 라이브러리를 작성하기 전에 사람들이 기존 라이브러리를 알고 있는지 알았습니다. Google 검색을 통해 분명한 것을 찾을 수 없습니다.

-시리아 스


검색 가능성 : omniauth(rails) 또는 python 과 동등한 것 social-auth. PHP (및 기타 일반적인 웹 서버 언어) 사용자도 자유롭게 추가 할 수 있습니다.
forivall

답변:


233

Connect 또는 Express에 대한 인증 프레임 워크를 찾고 있다면 Passport를 조사 할 가치가 있습니다. https://github.com/jaredhanson/passport

(공개 : 저는 Passport 개발자입니다)

connect-auth와 everyauth를 모두 조사한 후 Passport를 개발했습니다. 둘 다 훌륭한 모듈이지만 내 요구에 맞지 않았습니다. 나는 더 가볍고 눈에 거슬리지 않는 것을 원했습니다.

Passport는 별도의 모듈로 분류되므로 필요한 것만 사용하도록 선택할 수 있습니다 (필요한 경우에만 OAuth). Passport는 또한 응용 프로그램에 경로를 마운트하지 않으므로 인증시기 및 위치를 유연하게 결정할 수 있으며 인증 성공 또는 실패시 발생하는 상황을 제어 할 수 있습니다.

예를 들어, 양식 기반 (사용자 이름 및 비밀번호) 인증을 설정하는 2 단계 프로세스는 다음과 같습니다.

passport.use(new LocalStrategy(
  function(username, password, done) {
    // Find the user from your DB (MongoDB, CouchDB, other...)
    User.findOne({ username: username, password: password }, function (err, user) {
      done(err, user);
    });
  }
));

app.post('/login', 
  passport.authenticate('local', { failureRedirect: '/login' }),
  function(req, res) {
    // Authentication successful. Redirect home.
    res.redirect('/');
  });

Facebook, Twitter 등을 통해 인증을위한 추가 전략을 사용할 수 있습니다. 필요한 경우 사용자 지정 전략을 플러그인 할 수 있습니다.


노드 1의 모든 인증 패키지 중에서 여권을 선택했습니다. 잘 문서화되고 사용하기 쉬우 며 더 많은 전략을 지원합니다.
tech-man

현재 프로토 타입으로 여권을 사용하고 있는데 유지 관리가되지 않아 디자인이 좋지 않기 때문에 권장하지 않습니다. 예를 들어 req.session.messages를 사용할 수있을 때 connect-flash를 사용하도록 강제하고 웹 사이트에 광고 된 여권 Google은 더 이상 사용되지 않는 Google OpenId를 사용하기 때문에 구식이며 여권에 대한 링크가 없습니다. 그것을 대체 해야하는 google-oauth. 또한 이것은 인증 후 콜백의 서명입니다 done(null,false,{ message:'Incorrect username.' }). 모든 매개 변수가 무엇인지 모르기 때문에 끔찍합니다.
eloone

1
@eloone Google에서 선호하는 새로운 인증 방법을 가리 키도록 문서를 업데이트해야합니다. 언급했듯이 지원이 존재하며 잘 작동합니다. 디자인 관련 질문과 관련하여 Passport는 Connect-Flash를 사용하도록 강요하지 않으며 언급 한 인수는 안내서에 문서화되어 있습니다. 이해하는 데 도움이 필요하면 사람들이 귀하의 질문에 도움을 줄 수있는 포럼이 있습니다.
Jared Hanson

아무것도 아닙니다.하지만 방금 Passport 연결을 완료했습니다 (제공된 예제 사용). 아주 쉬워요! 가장 최근의 의견 이후 몇 년이 지났다는 것을 알고 있습니다. 누구든지 살펴볼 것을 권장합니다.
terary

89

세션 + If

좋은 라이브러리를 많이 찾지 못한 이유는 인증을 위해 라이브러리를 사용하는 것이 대부분 오버 엔지니어링이기 때문입니다.

당신이 찾고있는 것은 세션 바인더입니다 :)

if login and user == xxx and pwd == xxx 
   then store an authenticated=true into the session 
if logout destroy session

그게 다야.


connect-auth 플러그인이 갈 길이라는 결론에 동의하지 않습니다.

나는 또한 connect를 사용하고 있지만 두 가지 이유로 connect-auth를 사용하지 않습니다.

  1. IMHO는 매우 강력하고 읽기 쉬운 양파 링 연결 아키텍처 인 connect-auth를 끊습니다. 아니-내 의견 :). 연결 작동 방식과 양파 링 아이디어에 대한 아주 좋고 짧은 기사를 여기에서 찾을 수 있습니다 .

  2. 서면으로-데이터베이스 또는 파일과 함께 기본 또는 http 로그인을 사용하려는 경우. 연결 인증이 너무 큽니다. OAuth 1.0, OAuth 2.0 & Co와 같은 것들에 더 적합합니다.


연결을 통한 매우 간단한 인증

(완료되었습니다. 테스트를 위해 실행하십시오. 그러나 프로덕션 환경에서 사용하려면 https를 사용해야합니다) (그리고 REST-Principle-Compliant가 되려면 GET-Request b / c 대신 POST-Request를 사용해야합니다. 당신은 상태를 변경 :)

var connect = require('connect');
var urlparser = require('url');

var authCheck = function (req, res, next) {
    url = req.urlp = urlparser.parse(req.url, true);

    // ####
    // Logout
    if ( url.pathname == "/logout" ) {
      req.session.destroy();
    }

    // ####
    // Is User already validated?
    if (req.session && req.session.auth == true) {
      next(); // stop here and pass to the next onion ring of connect
      return;
    }

    // ########
    // Auth - Replace this example with your Database, Auth-File or other things
    // If Database, you need a Async callback...
    if ( url.pathname == "/login" && 
         url.query.name == "max" && 
         url.query.pwd == "herewego"  ) {
      req.session.auth = true;
      next();
      return;
    }

    // ####
    // This user is not authorized. Stop talking to him.
    res.writeHead(403);
    res.end('Sorry you are not authorized.\n\nFor a login use: /login?name=max&pwd=herewego');
    return;
}

var helloWorldContent = function (req, res, next) {
    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end('authorized. Walk around :) or use /logout to leave\n\nYou are currently at '+req.urlp.pathname);
}

var server = connect.createServer(
      connect.logger({ format: ':method :url' }),
      connect.cookieParser(),
      connect.session({ secret: 'foobar' }),
      connect.bodyParser(),
      authCheck,
      helloWorldContent
);

server.listen(3000);

노트

나는 1 년 전에이 진술을 썼으며 현재 활성 노드 프로젝트가 없습니다. 따라서 Express에 API 변경이있을 수 있습니다. 변경해야 할 경우 의견을 추가하십시오.


왜 connect-auth가 양파 / 레이어 패턴을 깨뜨 립니까? next ()를 사용하지 않기 때문입니까? 그럴 수 있습니까?
jpstrikesback

3
예. 연결의 기본 개념이므로 next ()를 사용해야합니다. Connect는 코드 구조의 레이어 아키텍처 / 형태를 가지고 있습니다. 그리고 모든 계층에는 next ()를 호출하지 않고 요청 실행을 중지 할 수있는 권한이 있습니다. 인증에 대해 이야기하는 경우 : 인증 계층에서 사용자에게 올바른 권한이 있는지 확인합니다. 모든 것이 괜찮다면 레이어는 next ()를 호출합니다. 그렇지 않으면이 인증 계층은 오류를 생성하고 next ()를 호출하지 않습니다.
Matthias

이건 내가 찾던 것입니다. connect-auth는 나에게 약간의 소화 불량을 주었다. 방금 앱에 처음 로그인했습니다. 정말 고마워.
Andy Ray

7
그래도 데이터베이스 백엔드에 연결하는 방법 (암호화 된 비밀번호로)에 응답하는 데 도움이되지 않습니다. 이 하나의 라이브러리가 과도하게 엔지니어링되었다는 의견에 감사하지만, 그렇지 않은 라이브러리가 있습니다. 또한 자체 인증 시스템을 작성하려면 Java에서 Struts를 사용했을 것입니다. OP와 마찬가지로 코드 1 줄에서 어떤 플러그인이 나를 위해 그것을 할 것인지 알고 싶습니다.
hendrixski

4
좋은 답변 Nivoc. 최신 버전의 connect tho에서는 작동하지 않습니다. 변경해야했습니다 ... cookieDecoder ()-> cookieParser () 및 bodyDecoder ()-> bodyParser () 및 helloWorldContent 함수에서 next () 호출을 제거하십시오. '헤더를 설정 한 후 헤더를 설정할 수 없습니다 '전송
마이클 Dausmann에게

26

연결 미들웨어에 대한 connect-auth 플러그인이 정확히 필요한 것 같습니다 : http://wiki.github.com/ciaranj/connect-auth/creating-a-form-based-strategy

express [ http://expressjs.com ]를 사용하고 있으므로 connect 플러그인은 express가 서브 클래스로 연결되어 있기 때문에 매우 잘 맞습니다.


1
당신이 한 일에 대한 예가 있습니까? 단순히 연결 인증이 필요하고 "req"에서 ".authenticate"를 호출하면 "TypeError : Object #에 'authenticate'메서드가 없습니다"가 표시됩니다.
Misha Reyzlin

1
IMHO이 플러그인은 간단한 http 인증을 위해 무겁게하는 방법입니다
Matthias

그리고이 플러그인은 연결 양파 링 아키텍처에 대해 작동합니다
마티아스

14

나는 기본적으로 같은 것을 찾고있었습니다. 특히, 나는 다음을 원했다.

  1. Connect의 미들웨어 기능을 감싸는 express.js를 사용하려면
  2. "양식 기반"인증
  3. 인증 된 경로를 세부적으로 제어
  4. 사용자 / 암호를위한 데이터베이스 백엔드
  5. 세션 사용

내가 한 일은 check_auth인증하려는 각 경로에 인수로 전달하는 자체 미들웨어 함수 를 작성하는 것이 었습니다 . check_auth세션을 확인하고 사용자가 로그인하지 않은 경우 다음과 같이 로그인 페이지로 리디렉션합니다.

function check_auth(req, res, next) {

  //  if the user isn't logged in, redirect them to a login page
  if(!req.session.login) {
    res.redirect("/login");
    return; // the buck stops here... we do not call next(), because
            // we don't want to proceed; instead we want to show a login page
  }

  //  the user is logged in, so call next()
  next();
}

그런 다음 각 경로 마다이 기능이 미들웨어로 전달되도록합니다. 예를 들면 다음과 같습니다.

app.get('/tasks', check_auth, function(req, res) {
    // snip
});

마지막으로 실제로 로그인 프로세스를 처리해야합니다. 이것은 간단합니다.

app.get('/login', function(req, res) {
  res.render("login", {layout:false});
});

app.post('/login', function(req, res) {

  // here, I'm using mongoose.js to search for the user in mongodb
  var user_query = UserModel.findOne({email:req.body.email}, function(err, user){
    if(err) {
      res.render("login", {layout:false, locals:{ error:err } });
      return;
    }

    if(!user || user.password != req.body.password) {
      res.render("login",
        {layout:false,
          locals:{ error:"Invalid login!", email:req.body.email }
        }
      );
    } else {
      // successful login; store the session info
      req.session.login = req.body.email;
      res.redirect("/");
    }
  });
});

어쨌든이 방법은 대부분 유연하고 단순하도록 설계되었습니다. 나는 그것을 향상시킬 수있는 많은 방법이 있다고 확신합니다. 당신이 있다면, 나는 당신의 의견을 매우 좋아합니다.

편집 : 이것은 간단한 예입니다. 프로덕션 시스템에서는 암호를 일반 텍스트로 저장하고 비교하지 않을 것입니다. 주석 작성자가 지적한 것처럼 암호 보안 관리에 도움이되는 lib가 있습니다.


2
이것은 암호를 저장하기 위해 bcrypt를 사용해야한다는 것을 제외하고는 좋습니다 (db의 일반 텍스트 아님). 여기에 대한 좋은 게시물이 있습니다 : devsmash.com/blog/…
chovy


7

다음은 내 프로젝트 중 하나의 기본 인증 코드입니다. 추가 인증 데이터 캐시와 함께 CouchDB에 대해 사용하지만 해당 코드를 제거했습니다.

요청 처리를 인증 방법으로 래핑하고 실패한 인증을위한 두 번째 콜백을 제공하십시오. 성공 콜백은 사용자 이름을 추가 매개 변수로 가져옵니다. 실패 콜백에서 자격 증명이 잘못되었거나 누락 된 요청을 올바르게 처리하는 것을 잊지 마십시오.

/**
 * Authenticate a request against this authentication instance.
 * 
 * @param request
 * @param failureCallback
 * @param successCallback
 * @return
 */
Auth.prototype.authenticate = function(request, failureCallback, successCallback)
{
    var requestUsername = "";
    var requestPassword = "";
    if (!request.headers['authorization'])
    {
        failureCallback();
    }
    else
    {
        var auth = this._decodeBase64(request.headers['authorization']);
        if (auth)
        {
            requestUsername = auth.username;
            requestPassword = auth.password;
        }
        else
        {
            failureCallback();
        }
    }


    //TODO: Query your database (don't forget to do so async)


    db.query( function(result)
    {
        if (result.username == requestUsername && result.password == requestPassword)
        {
            successCallback(requestUsername);
        }
        else
        {
            failureCallback();
        }
    });

};


/**
 * Internal method for extracting username and password out of a Basic
 * Authentication header field.
 * 
 * @param headerValue
 * @return
 */
Auth.prototype._decodeBase64 = function(headerValue)
{
    var value;
    if (value = headerValue.match("^Basic\\s([A-Za-z0-9+/=]+)$"))
    {
        var auth = (new Buffer(value[1] || "", "base64")).toString("ascii");
        return {
            username : auth.slice(0, auth.indexOf(':')),
            password : auth.slice(auth.indexOf(':') + 1, auth.length)
        };
    }
    else
    {
        return null;
    }

};

양식 기반 인증을 선호하는 기본 인증을 피하고 싶었습니다. 이것은 기본 인증 문제에 대한 우아한 솔루션입니다. 그래도 좋은 인증 프레임 워크를 찾은 것 같습니다 (connect-auth-connectjs 위에 있음)
shreddd


3

몇 년이 지났고 Express 용 인증 솔루션을 소개하고 싶습니다. Lockit 이라고 합니다. GitHub 에서 프로젝트를 찾고 내 블로그 에서 짧은 소개를 찾을 수 있습니다 .

기존 솔루션과의 차이점은 무엇입니까?

  • 쉽게 사용할 수 : 귀하의 DB 설정, 설치 NPM, require('lockit'), lockit(app), 수행
  • 이미 내장 된 경로 (/ signup, / login, / forgot-password 등)
  • 이미 내장 된보기 (부트 스트랩 기반이지만 자신의보기를 쉽게 사용할 수 있음)
  • AngularJS / Ember.js 단일 페이지 앱을위한 JSON 통신을 지원합니다
  • OAuth 및 OpenID는 지원하지 않습니다. 만 username하고 password.
  • 그것은 즉시 여러 데이터베이스 (CouchDB, MongoDB, SQL)와 함께 작동합니다
  • 테스트가 있습니다 (Drywall에 대한 테스트를 찾을 수 없습니다)
  • 적극적으로 유지 관리됩니다 (모든 인증과 비교)
  • 이메일 확인 및 비밀번호 프로세스를 잊어 버렸습니다 (Password에서 지원하지 않는 토큰으로 이메일 전송)
  • 모듈성 : 필요한 것만 사용하십시오
  • 유연성 : 모든 것을 사용자 정의

예제를 살펴보십시오 .


2

Passport를 사용하여 사용자 로그인 시스템을 구현 하고 사용자 관리 관리자 패널이있는 Drywall 이라는 프로젝트 가 있습니다. Django가 가지고 있지만 Node.js와 비슷한 기능을 갖춘 완전한 사용자 인증 및 관리 시스템을 찾고 있다면 이것이 바로 그것입니다. 사용자 인증 및 관리 시스템이 필요한 노드 앱을 구축하기에 정말 좋은 출발점이되었습니다. Passport 작동 방식에 대한 정보는 Jared Hanson의 답변 을 참조하십시오 .



1

Angular 클라이언트에 사용자 인증을 제공하는 API에 대해 mongo를 사용하는 간단한 예

app.js에서

var express = require('express');
var MongoStore = require('connect-mongo')(express);

// ...

app.use(express.cookieParser());
// obviously change db settings to suit
app.use(express.session({
    secret: 'blah1234',
    store: new MongoStore({
        db: 'dbname',
        host: 'localhost',
        port: 27017
    })
}));

app.use(app.router);

경로는 다음과 같습니다.

// (mongo connection stuff)

exports.login = function(req, res) {

    var email = req.body.email;
    // use bcrypt in production for password hashing
    var password = req.body.password;

    db.collection('users', function(err, collection) {
        collection.findOne({'email': email, 'password': password}, function(err, user) {
            if (err) {
                res.send(500);
            } else {
                if(user !== null) {
                    req.session.user = user;
                    res.send(200);
                } else {
                    res.send(401);
                }
            }
        });
    });
};

그런 다음 인증이 필요한 경로에서 사용자 세션을 확인할 수 있습니다.

if (!req.session.user) {
    res.send(403);
}

0

다음은 타임 스탬프 토큰을 사용하는 새로운 인증 라이브러리입니다. 토큰은 데이터베이스에 저장하지 않고도 이메일로 보내거나 문자 메시지를 보낼 수 있습니다. 암호없는 인증 또는 2 단계 인증에 사용할 수 있습니다.

https://github.com/vote539/easy-no-password

공개 : 저는이 도서관의 개발자입니다.


0

Microsoft Windows 사용자 계정으로 SSO (Single Sign On)로 인증이 필요한 경우 https://github.com/jlguenego/node-expose-sspi를 시도해보십시오 .

req.sso모든 클라이언트 사용자 정보 (로그인, 표시 이름, sid, 그룹)가 포함 된 객체를 제공합니다 .

const express = require("express");
const { sso, sspi } = require("node-expose-sspi");

sso.config.debug = false;

const app = express();

app.use(sso.auth());

app.use((req, res, next) => {
  res.json({
    sso: req.sso
  });
});

app.listen(3000, () => console.log("Server started on port 3000"));

면책 조항 : 저는 node-expose-sspi의 저자입니다.


0

달콤한 인증

경량의 제로 구성 사용자 인증 모듈. 별도의 데이터베이스가 필요하지 않습니다.

https://www.npmjs.com/package/sweet-auth

다음과 같이 간단합니다.

app.get('/private-page', (req, res) => {

    if (req.user.isAuthorized) {
        // user is logged in! send the requested page
        // you can access req.user.email
    }
    else {
        // user not logged in. redirect to login page
    }
})
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.