LoginSignup
3
4

More than 3 years have passed since last update.

socket.io にセッション情報を渡す

Posted at

socket.io + express-session + passport

hidden.in というsocket.ioを使ったビデオ会議をするプログラムを使用していました。
その際に、ユーザー名を表示させたいとの要望があり実装した備忘録です。

各バージョン

  • Node v12.13.1
  • express-session 1.17.1
  • passport 0.4.1
  • passport-local 1.0.0

hidden.inのインストール、使用方法については記事がありますので、参考にしてください。(また、後日まとめたいと思います)
インストール済みを想定して話を進めます。

少し話はそれますが、フォームにユーザー名を入力させてemitするといけるんちゃんと考え、実装したのですが、ブラウザをリロードすると消えてしまう為、ダメでした。

では、実装手順です

  1. express-sessionとpassportとpassport-localをinstallする
tarminal
npm install i express-session passport passport-local
//インストール完了

2 requireして認証を実行する

index.js
var passport = require('passport');
var session = require('express-session');
var localStrategy = require('passport-local').Strategy;

var app = express();
var sessionMiddlewere = session({
  resave:false,
  saveUninitialized:false,
  secret:'passport test',
  cookie:{
    httpOnly:false,
    secure:false,
  }
});
app.session = sessionMiddlewere;
app.use(sessionMiddlewere);

app.use(passport.initialize());
app.use(passport.session());
passport.use(new localStrategy({
  usernameField:'username',
  passwordField:'password',
  passReqToCallback: true,
  session:false,
},function(req,username,password,done){
  process.nextTick(function(){
    if(username === 'test' && password === 'test'){
      return done(null,username);
    }else{
      console.log('Login Error');
      return done(null,false,{message:'パスワードが正しくありません'});
    }
  })
}));

passport.serializeUser(function(user,done){
  done(null,user);
});

passport.deserializeUser(function(user,done){
  done(null,user);
});
var io = require('socket.io').listen(server);
io.use(function(socket,next){
  sessionMiddlewere(socket.request,socket.request.res,next);
});
//詳細⬇️

今回はユーザー名testパスワードtestのみログインできるようにしています。
また、後半のio.useの部分のところでsocket.ioに対してsessionMiddlewereを使えるようにしていると思っています。

3 ルーティングの際にログイン済か認証する

index.js
app.get('/',sessionCheck);

function sessionCheck(req,res){
  if(req.user){
    res.render('index.ejs', { 
      title: 'Express',
      user: req.user 
    });
  }else{
    res.redirect('/login');
  }
}

app.get('/login',(req,res) => {
  res.render('login.ejs',{
    title:'Login Page',
    user: req.user
  });
});

app.post('/login',passport.authenticate('local',{
  successRedirect:'/',
  failureRedirect:'/login',
  session:true,
}));

app.get('/logout',(req,res) => {
  req.logOut();
  res.redirect('/');
});



app.get("/:channel",(req,res) =>  {
  if(req.user){
    res.render('screen.ejs', { 
      title: 'Express',
      user: req.user 
    });

  }else{
    res.redirect('/login');
  }
});

ここでのポイントはログインをしていなかったら、/loginに飛ばす処理をしているのと、app.post(/login)のところで、ログイン判定をしてリダイレクトルートを決めているところだと思います。

4 login.ejsを作成する

views/login.ejs
!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><%= title %> </title>
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" >
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
    <link rel='stylesheet' href='/css/style.css' />
</head>
<body>
    <div class="container">
        <h1>Login Page</h1>
        <p class="lead">ログインページです</p><!-- /.lead -->
        <br>
        <form action="/login" method="post">
            <div class="form-group">
                <input type="text" name="username" id="username" placeholder="Enter UserName" class="form-control">
            </div><!-- /.form-group -->
            <div class="form-group">
                <input type="password" name="password" id="password" class="form-control">
                <button type="submit" class="btn btn-default">送信</button><!-- /.btn btn-default -->
                &nbsp;
                <a href="/"><button class="btn btn-primary">キャンセル</button><!-- /.btn btn-primary --></a>
            </div><!-- /.form-control -->
        </form>
    </div><!-- /.container -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" ></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>

</body>
</html>

これでログインは実装できたのですが、サーバーサイド、クライアントサイドのsocket.ioでのセッション情報の取得の仕方は

index.js
io.sockets.on('connection', function (socket) {
    console.log(socket.request.session.passport.user);
}

とすると認証されたユーザー情報が取得できるので、あとはこれをejsファイルで表示させてレイアウト整えるとユーザー名の表示の実装が出来る様になりました。
ユーザー名を表示させるプログラムについては、長くなったので別記事を用意したいと思います。

参考記事の皆様

node.js socket.io上でsessionを使う
Node.js+Express+Passport を使ってみた

3
4
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
3
4