LoginSignup
23
34

More than 5 years have passed since last update.

expressでユーザー管理+MySQL

Last updated at Posted at 2018-07-19

expressでは、passportの認証機能を利用するのが便利です。
twitterやfacebookなどとも連携できます。
ここではローカルでの認証について、アウトプットとしてまとめました。

expressアプリの作成

$ npm install -g express-generator
$ express --view=pug your-app-name
$ cd your-app-name
$ npm install

以降、

$ npm start

でアプリケーションを起動させます。
http://localhost:3000

必要項目のインストール

$ npm install --save passport
$ npm install --save passport-local
$ npm install --save express-session

ログイン実装

app.js
// 既に色々入っているので、そこへ追加
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var session = require('express-session');

// signinページの追加
var signinRouter = require('.routes/signin');
app.use('/signin');

// session, passport.initialize, passport.sessionは以下の順番で追加
app.use(session({
  secret: "testing",
  resave: false,
  saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());

// authentication
passport.serializeUser(function(username, done) {
  console.log('serializeUser');
  done(null, username);
});

passport.deserializeUser(function(username, done) {
  console.log('deserializeUser');
  done(null, {name:username});
});

passport.use(new LocalStrategy(
  {
    // signinのformで定義したnameの要素をセット
    usernameField: "username",
    passwordField: "password"
  },
  function(username, password, done){
    // ここでは、データベースを使わずに、仮にusernameとpasswordを固定で入れています。
    if(username == "test" && password == 123456789){
      return done(null, username);
    }
    return done(null, false, {message: "invalid"});
  }
));

app.post('/signin',
  passport.authenticate('local',
    {
      failureRedirect: "/signin"
    }
  ),
  function(req, res, next){
    // res.redirect("/")でreq.userが渡せなかったので、ここでfetchを使っています。
    // https://github.com/jaredhanson/passport/issues/244
    // fetchは以下のようにインストール
    // npm install --save isomorphic-fetch
    // var fetch = require('isomorphic-fetch');
    fetch("http://localhost:3000/signin",
      {
        credentials: "include"
      }
    ).then(function(){
      res.redirect("/");
    }).catch(function(e){
      console.log(e);
    });
  }
);

で、index.pugへリダイレクトした時に、そのページ上にログインしたユーザーの名前を表示します。

index.js
var express = require('express');
var router = express.Router();

// index.pugをgetした時にコールバックを実行
router.get('/', function(req, res, next) {
  console.log(req.user); // {name:'test'}
  if (req.user) { // ログインしているユーザーが存在する場合のみ有効
    res.render("index", { username: req.user.name});
  } else { // ユーザーが存在しなければ、サインインページへ飛ばされる
    res.redirect('/signin');
  }
});

module.exports = router;
index.pug
extends layout

block content
  h1= username
  p Welcome to Express

こんな感じでtestの文字が出てきます。
Screen Shot 2018-07-18 at 23.15.22.png

signin.jsはindex.jsをコピペしてsignin用に書き換えるだけで良いです。

signin.js
var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
  res.render("signin", {});
});

module.exports = router;

一応signin.pugも

signin.pug
extends layout

block content
  form(action="/signin" method="post")
    .username
      label username
      input(type="text" name="username") // nameはnew LocalStrategyのところで使います。
    .password
      label password
      input(type="password" name="password") // nameはnew LocalStrategyのところで使います。
    .signin
      input(type="submit")

ログイン時にconsole.log('serializeUser')とconsole.log('deserializeUser')が実行されていることを確認しましょう。
serializeUserだけがコンソールで出力されていてもdeserializeUserが出力されていなければ、ログインは成功していません。
その時は、app.use時のsession、passport.initilizer、passport.sessionを書く順番がおかしくなっていないかとか、誤字脱字等がないかどうかとか、チェックしていってください。

MySQLのユーザー情報を基にログイン

mysqlで適当にデータベースを作ります。

mysql> create table users (id int not null primary key, username varchar(20), password int);

とかにして、

mysql> insert into users values (1, 'test', 123456789);

みたいにデータを入れておきます。
次にapp.jsでmysqlを使い、データを取り出してログイン時に入力された値と照合させるようにします。

app.js
// npm install --save mysql2
var mysql = require('mysql2');
var connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'your-password', // mysqlの自分のパスワード
  database: 'testdb' // db名は自分で自由に作った名前を当てはめる
});

// 上で書き込んだpassport.useの部分を書き換えます。
passport.use(new LocalStrategy(
  {
    usernameField: "username",
    passwordField: "password"
  },
  function(username, password, done){
    connection.query("select * from users;", function(err, users) {
      // usernameもpasswordもユニーク前提
      var usernames = [];
      var passwords = [];
      for (i = 0; i < users.length; i++) {
        usernames.push(users[i].username);
        // input(type="password")で渡される値はstringのようなので、
        // データベースから取り出した値もstringにしています。
        var pw = users[i].password.toString();
        passwords.push(pw);
      }
      if (usernames.includes(username) && passwords.includes(password)) {
        return done(null, username);
      }
      return done(null, false, {message: "invalid"});
    });
  }
));

これで、ログイン時に
ユーザー名: test
パスワード: 123456789
を入れてあげると、ログインできるようになります。

サインアップは、サインアップのフォームを作って、post時に/signupへやってきた時のコールバックにロジックを書いてあげれば良いです。

app.js
app.post('/signup', function(req, res, next){
  connection.query('select * from users;', function(err, users){
    connection.query('insert into users set ? ;', {
        username: req.body.username,
        email: req.body.email,
        password: req.body.password,
        created_at: new Date(),
        updated_at: new Date()
      },
      function(err){
        console.log("サインアップに関するエラー: " + err);
        res.redirect("/signin");
      }
    );
  });
});

まあ、こんな感じで。

サインアウトは、

app.js
app.get('/signout', function(req, res, next) {
  req.logout();
  console.log('ログアウトしました');
  res.redirect('/');
});

これだけでOKです。
いい感じのところにサインアウトボタンを配置してあげてください。

23
34
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
34