セッション判定回りを修正

This commit is contained in:
hina ntki 2024-08-12 17:11:32 +09:00
parent 7e580d75d0
commit f6dc93a9ab
5 changed files with 47 additions and 9 deletions

4
.gitignore vendored
View File

@ -173,4 +173,6 @@ poetry.toml
# LSP config files
pyrightconfig.json
# End of https://www.toptal.com/developers/gitignore/api/python
# End of https://www.toptal.com/developers/gitignore/api/python
web/data/

1
_.env Normal file
View File

@ -0,0 +1 @@
DISCORD_TOKEN=

View File

@ -5,7 +5,7 @@ services:
- ./bot:/bot
- ./bucket:/bot/bucket
environment:
- DISCORD_TOKEN=MTIyNjIwMTA4ODg1NjgyMTg4MQ.GH0q-p.5A8k4UCGXK5UT6g4uCksFNHhAky9EvRQLuZckQ
- DISCORD_TOKEN=${DISCORD_TOKEN}
web:
build: ./web
volumes:

View File

@ -1,12 +1,16 @@
from flask import request, session, redirect, url_for, render_template, g, jsonify
from flask import request, session, redirect, url_for, render_template, jsonify
import bcrypt
import secrets
from db import get_db
from models import Account, ActiveSession
import logging
from datetime import datetime, timedelta
logger = logging.getLogger(__name__)
# セッションタイムアウトの設定3分
SESSION_TIMEOUT = timedelta(minutes=5)
def login_required(f):
def decorated_function(*args, **kwargs):
if not check_login(session, logger):
@ -19,12 +23,24 @@ def check_login(session, logger):
if 'logged_in' not in session or not session['logged_in']:
logger.info("セッションにログイン情報がありません")
return False
# セッションタイムアウトのチェック
last_access_time = session.get('last_access_time')
if last_access_time:
last_access_time = datetime.strptime(last_access_time, '%Y-%m-%d %H:%M:%S.%f')
if datetime.now() - last_access_time > SESSION_TIMEOUT:
logger.info("セッションがタイムアウトしました")
logout() # セッションをクリアし、ログアウト
return False
db = get_db()
active_session_count = db.query(ActiveSession).filter_by(session_id=session['session_id']).count()
if active_session_count != 1:
logger.info(f"セッションID {session['session_id']} のアクティブセッション数: {active_session_count}")
return False
# 最後のアクセス時間を更新
session['last_access_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
return True
def login():
@ -33,12 +49,26 @@ def login():
password = request.form['password'].encode('utf-8')
db = get_db()
account = db.query(Account).filter_by(user_id=user_id).first()
if account and bcrypt.checkpw(password, account.password.encode('utf-8')):
active_sessions = db.query(ActiveSession).count()
if active_sessions >= 1:
return "他のユーザーが既にログインしています。", 403
# 既存のアクティブセッションをチェック
existing_session = db.query(ActiveSession).filter_by(user_id=account.id).first()
if existing_session:
# セッションのタイムアウトを確認
last_active = existing_session.last_active
if last_active and datetime.now() - last_active > SESSION_TIMEOUT:
# セッションがタイムアウトしている場合、削除
db.delete(existing_session)
db.commit()
else:
return "他のユーザーが既にログインしています。", 403
# 新しいセッションの作成
session['logged_in'] = True
new_session = ActiveSession(session_id=session['session_id'])
session['session_id'] = secrets.token_hex(16)
session['last_access_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
new_session = ActiveSession(session_id=session['session_id'], user_id=account.id, last_active=datetime.now())
db.add(new_session)
db.commit()
return redirect(url_for('index_route'))
@ -48,7 +78,7 @@ def login():
def logout():
db = get_db()
db.query(ActiveSession).filter_by(session_id=session['session_id']).delete()
db.query(ActiveSession).filter_by(session_id=session.get('session_id')).delete()
db.commit()
session.clear()
return redirect(url_for('login_route'))

View File

@ -1,5 +1,6 @@
from sqlalchemy import Column, Integer, String, TIMESTAMP
from sqlalchemy import Column, Integer, String, TIMESTAMP, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
Base = declarative_base()
@ -9,11 +10,15 @@ class Account(Base):
user_id = Column(String)
password = Column(String)
active_sessions = relationship("ActiveSession", back_populates="account")
class ActiveSession(Base):
__tablename__ = 'active_sessions'
id = Column(Integer, primary_key=True)
session_id = Column(String)
last_active = Column(TIMESTAMP)
user_id = Column(Integer, ForeignKey('accounts.id'))
account = relationship("Account", back_populates="active_sessions")
class ChannelId(Base):
__tablename__ = 'channel_ids'