[英]the value of 'current_user.is_authenticated' is always False in Template
[英]current_user.is_authenticated always False (TACACS and flask_login)
我正在嘗試實現基於 TACACS+ 的 flask_login 系統,但由於current_user.is_authenticated
始終為 false,因此我被卡住了。 我沒有使用任何本地數據庫 - 通過我的登錄表單提交的用戶名和密碼直接傳遞給 TACACS。
我的自定義User
類實現了 此處flask_login 文檔中描述的 3 個屬性和 1 個方法:
下面,您將找到每個文件的相關代碼,以便您可以在自己的環境中進行設置。
下面有很多信息,所以我想盡可能清楚地分享我的實際問題:
User
類連接到current_user
代理? 我的實現的潛在問題是,當我使用@login_required
裝飾器訪問任何燒瓶路由時,應用程序認為用戶未登錄並將其重定向到登錄頁面。 我已經確定它是因為current_user.is_authenticated
屬性從不為 True。
應用程序
from flask import Flask, request, render_template, url_for, flash, redirect, session, Markup
from forms import LoginForm
from flask_login import LoginManager, login_user, logout_user, login_required, current_user, UserMixin
import user_auth as auth
# TODO: Save the user_dict to a pickle file so that users persist between service restarts
user_dict = {}
class User():
def __init__(self, username, password):
self.username = username
self.password = password
# Send TACACS authentication and authorization requests
priv = auth.login(self.username, self.password)
if priv:
self.is_authenticated = True
self.is_active = True
self.is_anonymous = False
if priv == 'admin':
self.priv_lvl = 15
elif priv == 'user':
self.priv_lvl = 10
elif priv == 'employee':
self.priv_lvl = 5
else:
self.is_authenticated = False
self.is_anonymous = True
self.priv_lvl = -1
def get_id(self):
return self.username
app = Flask(__name__)
app.secret_key = 'mysecretkey!'
app.static_url_path = 'static/'
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'index'
@login_manager.user_loader
def load_user(user):
global user_dict
if user in user_dict.keys():
return user_dict[user]
@app.route('/', methods=['GET', 'POST'])
def index():
form = LoginForm()
try:
if user.is_authenticated:
return render_template('test.html')
except UnboundLocalError:
user = None
pass
if form.validate_on_submit():
username = form.username.data
password = form.password.data
user = User(username, password)
username = password = None
print(f"User {user.username} logged in. User authenticated: {user.is_authenticated}")
print(f"Is current_user authenticated? {current_user.is_authenticated}")
if user.priv_lvl >= 0:
# SOLUTION -> The following was missing
login_user(user, remember=form.remember.data)
user_dict.update({
user.username : user
})
# END SOLUTION
print("User is authorized to view test.html.")
return render_template('test.html', current_user=current_user, user=user)
else:
flash(f'Invalid login', 'error')
return render_template('index.html', title='Login Required', form=form, user=user)
return render_template('index.html', title='Login Required', form=form, user=user)
@app.route("/home", methods=['GET'])
@login_required
def home():
return render_template('test.html')
user_auth.py
from tacacs_plus.client import TACACSClient
from tacacs_plus.flags import TAC_PLUS_ACCT_FLAG_START, TAC_PLUS_ACCT_FLAG_WATCHDOG, TAC_PLUS_ACCT_FLAG_STOP
import socket
ISE = 'my.ip.add.rr'
auth_key = 'password'
def login(username, password):
cli = TACACSClient(ISE, 49, auth_key, timeout=10, family=socket.AF_INET)
authen = cli.authenticate(username, password)
if authen.valid:
author = cli.authorize(username, arguments=[b"service=", b"protocol="])
if author.valid:
role = author.arguments[0].decode('utf-8')
if 'user' in role.lower():
priv = 'user'
elif 'admin' in role.lower():
priv = 'admin'
else:
print("User has authenticated successfully, but failed authorization.")
priv = 'employee'
else:
print("User failed authentication.")
priv = None
return priv
表格.py
from flask_wtf import FlaskForm
from wtforms import Form, StringField, SubmitField, BooleanField
from wtforms.fields import PasswordField
from wtforms.validators import DataRequired
class LoginForm(FlaskForm):
username = StringField("Username", validators=[DataRequired()])
password = PasswordField("Password", validators=[DataRequired()])
remember = BooleanField("Remember Me")
submit = SubmitField("Login")
索引.html
<div id='login-container' class='container'>
<form method="POST" action="">
{{ form.csrf_token }}
{{ form.hidden_tag() }}
<fieldset>
<legend class="border-bottom mb-4">Login</legend>
<p>Use your TACACS credentials.</p>
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class="alerts">
{% for message in messages %}
<div class="alert alert-warning" role="alert">{{ message }}</div>
{% endfor %}
</div>
{% endif %}
{% endwith %}
<div class='form-group'>
{{ form.username.label(class="form-control-label") }}
{% if form.username.errors %}
{{ form.username(class="form-control form-control-lg is-invalid") }}
<div class='custom-invalid-feedback'>
{% for error in form.username.errors %}
<span>
{{ error }}
</span>
{% endfor %}
</div>
{% else %}
{{ form.username(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class='form-group'>
{{ form.password.label(class="form-control-label") }}
{% if form.password.errors %}
{{ form.password(class="form-control form-control-lg is-invalid") }}
<div class='custom-invalid-feedback'>
{% for error in form.password.errors %}
<span>
{{ error }}
</span>
{% endfor %}
</div>
{% else %}
{{ form.password(class="form-control form-control-lg") }}
{% endif %}
</div>
{{form.remember.label}}
{{form.remember}}
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</fieldset>
</form>
</div>
測試.html
{% if user.is_authenticated %}
<h2>My custom user class is authenticated</h2>
{% else %}
<h2> My custom user class is NOT authenticated</h2>
{% endif %}
{% if current_user.is_authenticated %}
<h2> current_user is authenticated</h2>
{% else %}
<h2>current_user is NOT authenticated</h2>
{% endif %}
requirements.txt(以防您想在自己的環境中進行測試)
Jinja2==2.10
dominate==2.5.1
Flask==1.1.1
flask_login==0.5.0
flask_wtf==0.14.3
plotly==4.5.3
tacacs_plus==2.6
WTForms==2.2.1
注意:如果您想在自己的應用程序中進行測試並且不想打擾 TACACS,請手動將priv
設置為admin
或user
當我使用有效憑據登錄時,這是我從控制台看到的內容:
User LetMeIn logged in. User authenticated: True
Is current_user authenticated? False
User is authorized to view test.html.
...在我瀏覽器的 test.html 頁面上,我看到
我在第四次剖析我的代碼后想通了。
簡單地說,我錯過了 login_user() 函數調用。 這是將自定義 User 類關聯到 flask_login current_user
關聯的原因。
我還需要創建一個簡單的本地用戶名存儲方法,以便所需的load_user
函數可以正常工作。 為此,我添加了一個全局可訪問的字典,該字典將我的自定義 User 對象存儲為與保存用戶名的鍵相關聯的值。
我將使用這些更改更新我原始帖子中的代碼片段,希望我的努力將來對某人有用。 我在網上找不到太多關於將 TACACS 與flask_login 集成的信息。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.