# 問題3 (v) ###### tags: `Flask` ## @login_required ![](https://i.imgur.com/QZv18h0.png) ![](https://i.imgur.com/7e5zYUJ.png) :::warning 已解決 --- * 應該是沒有記錄到登入的狀態 * `__init__.py 29行`:`UserRegister.query.filter_by(id=userID).first()` 可以登入,可是沒有辦法執行 `@login_required` * 因為預設的session紀錄時間是365天,沒有去清除chrome快取的話他會一直紀錄帳號登入的狀態,所以沒有辦法執行`@login_required` 的重新導向至 `login()` ### 解決方法 * 將 `@login_manager.user_loader` 移至 `model.py` 內並更改成: ```python= # 加入user_loader之後login_required才能順利跳轉 # 因為login_user()需要一個回傳的數值才有辦法確認user狀態 @login_manager.user_loader def load_user(userID): from member.setting.model import UserRegister user = UserRegister.query.filter_by(id=userID).first() if user: return user return None ``` * 在 `config.py` 中設置: `REMEMBER_COOKIE_DURATION = timedelta(minutes=1)` :是否記住使用者 `PERMANENT_SESSION_LIFETIME = timedelta(minutes=1)` :清除session的時間 * 如果有設置 `PERMANENT_SESSION_LIFETIME` 要在 `view.py` 中新增: ```python= @app.route('/login', methods=['GET', 'POST']) def login(): ... if user.check_password(form.password.data): session.permanent = True login_user(user, form.remember_me.data) ... ``` ::: --- ## view ```python= @app.route('/login', methods=['GET', 'POST']) def login(): form = FormLogin() if form.validate_on_submit(): user = UserRegister.query.filter_by(email=form.email.data).first() if user: if user.check_password(form.password.data): login_user(user, form.remember_me.data) next = request.args.get('next') print(next) if not next_is_valid(next) or next==None: return render_template('login/successL.html', name=user.username) return redirect(next or url_for('index')) else: flash('錯誤的E-mail或密碼') else: flash('錯誤的E-mail或密碼') return render_template('login/login.html', form=form) def next_is_valid(url): # 需要手動刻一個能辨識取得的url是否和來源相同 return True @app.route('/userinfo') @login_required def index(): return ':->' ``` ## _\_init\_\_ ```python= from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_bootstrap import Bootstrap from config import Config from flask_migrate import Migrate from flask_bcrypt import Bcrypt from flask_mail import Mail from flask_login import LoginManager app = Flask(__name__) app.config.from_object(Config) mail = Mail(app) bootstrap = Bootstrap(app) db = SQLAlchemy(app) bcrypt = Bcrypt(app) migrate = Migrate(app, db) login_manager = LoginManager(app) login_manager.init_app(app) login_manager.login_view = 'login' login_manager.login_message = '請登入系統來檢視這個頁面' @login_manager.user_loader # 加入user_loader之後login_required才能順利跳轉 def load_user(userID): from member.setting.model import UserRegister try: return UserRegister.query.get(UserRegister.id==userID) except: return None from .setting import view ```