如何解决Flask登录中的谷歌登录问题?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何解决Flask登录中的谷歌登录问题?相关的知识,希望对你有一定的参考价值。
我正试图将Google Signin与我的Flask应用集成。我正在使用Flask、Flask-Login和Flask-WTF。我有一个可以工作的应用程序,允许我正常登录、注册和注销。到目前为止,我可以启动Google SigninAuthorization过程,但一旦我选择我的Google账户,应用程序就会崩溃。
我试了很多方法才达到现在的效果,但现在我被卡住了。我认为我的问题是当谷歌试图将我的谷歌帐户与我的数据库连接时。然而,我不太确定从这里去哪里。
import os
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1'
from flask import Flask, render_template, redirect, url_for
from flask_bootstrap import Bootstrap
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField
from wtforms.validators import InputRequired, Email, Length
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from flask_admin import Admin, AdminIndexView
from flask_admin.contrib.sqla import ModelView
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from flask_dance.contrib.google import make_google_blueprint, google
from flask_dance.consumer.storage.sqla import OAuthConsumerMixin, SQLAlchemyStorage
from flask_dance.consumer import oauth_authorized
from sqlalchemy.orm.exc import NoResultFound
app = Flask(__name__)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = 'Thisissupposedtobesecret!'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////sqlite3/login.db'
bootstrap = Bootstrap(app)
db = SQLAlchemy(app)
app.config["GOOGLE_OAUTH_CLIENT_ID"] = ("123")
app.config["GOOGLE_OAUTH_CLIENT_SECRET"] = ("123")
app.config["OAUTHLIB_RELAX_TOKEN_SCOPE"] = True
app.config["OAUTHLIB_INSECURE_TRANSPORT"] = True
google_bp = make_google_blueprint(scope=["https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email openid"])
app.register_blueprint(google_bp, url_prefix="/google_login")
login_manager = LoginManager(app)
login_manager.init_app(app)
login_manager.login_view = 'login'
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(15), unique=True)
email = db.Column(db.String(50), unique=True)
password = db.Column(db.String(80))
def __init__(self, username, email, password):
self.username = username
self.email = email
self.password = password
def is_authenticated(self):
return True
def is_active(self):
return True
def is_anonymous(self):
return False
def get_id(self):
return str(self.id)
def __repr__(self):
return '<User %r>' %(self.username)
class OAuth(OAuthConsumerMixin, db.Model):
user_id = db.Column(db.Integer, db.ForeignKey(User.id))
user = db.relationship(User)
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
google_bp.storage = SQLAlchemyStorage(OAuth, db.session, user=current_user)
class MyModelView(ModelView):
def is_accessible(self):
return current_user.is_authenciated
def inaccessible_callback(self, name, **kwargs):
return redirect(url_for('login'))
class MyAdminIndexView(AdminIndexView):
def is_accessible(self):
return current_user.is_authenticated
admin = Admin(app, index_view=MyAdminIndexView())
admin.add_view(ModelView(User, db.session))
admin.add_view(ModelView(OAuth, db.session))
class LoginForm(FlaskForm):
username = StringField('username', validators=[InputRequired(), Length(min=4, max=15)])
password = PasswordField('password', validators=[InputRequired(), Length(min=8, max=80)])
remember = BooleanField('remember me')
class RegisterForm(FlaskForm):
email = StringField('email', validators=[InputRequired(), Email(message='Invalid email'), Length(max=50)])
username = StringField('username', validators=[InputRequired(), Length(min=4, max=15)])
password = PasswordField('password', validators=[InputRequired(), Length(min=8, max=80)])
@app.route('/')
def index():
return render_template('index.html')
@app.route("/google")
def google_login():
if not google.authorized:
return redirect(url_for('google.login'))
return redirect(url_for('dashboard'))
@oauth_authorized.connect_via (google_bp)
def google_is_logged_in(blueprint,token):
account_info = blueprint.session.get('/oauth2/v3/userinfo')
if account_info.ok:
account_info_json = account_info.json()
username = account_info_json['name']
query = User.query.filter_by(username=form.username.data)
try:
user = query.first()
except NoResultFound:
user = User(username=form.username.data)
db.session.add(user)
db.session.commit()
login_user(user)
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
user.is_active = True
if user:
if check_password_hash(user.password, form.password.data):
login_user(user, remember=form.remember.data)
return redirect(url_for('dashboard'))
if not user:
user = User(username=form.username.data)
db.session.add(user)
db.session.commit()
login_user(user)
return '<h1>Invalid username or password</h1>'
return '<h1>' + form.username.data + ' ' + form.password.data + '</h1>'
return render_template('login.html', form=form)
@app.route('/signup', methods=['GET', 'POST'])
def signup():
form = RegisterForm()
if form.validate_on_submit():
hashed_password = generate_password_hash(form.password.data, method='sha256')
new_user = User(username=form.username.data, email=form.email.data, password=hashed_password)
db.session.add(new_user)
db.session.commit()
return '<h1>New user has been created!</h1>'
return '<h1>' + form.username.data + ' ' + form.email.data + ' ' + form.password.data + '</h1>'
return render_template('signup.html', form=form)
@app.route('/dashboard')
@login_required
def dashboard():
return render_template('dashboard.html', name=current_user.username)
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('index'))
if __name__ == '__main__':
app.run(debug=True)
'''
我可以正常登录、注销和注册。然而,当我尝试启动谷歌登录时,当我选择我的谷歌帐户时,应用程序立即崩溃。以下是我收到的错误信息。
127.0.0.1 - - [05/Aug/2019 20:53:56] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [05/Aug/2019 20:54:01] "GET /google HTTP/1.1" 302 -
127.0.0.1 - - [05/Aug/2019 20:54:01] "GET /google_login/google HTTP/1.1" 302 -
[2019-08-05 20:54:05,320] ERROR in app: Exception on /google_login/google/authorized [GET]
Traceback (most recent call last):
File "D:\PyCharm Projects\Plutone\lib\site-packages\flask\app.py", line 2311, in wsgi_app
response = self.full_dispatch_request()
File "D:\PyCharm Projects\Plutone\lib\site-packages\flask\app.py", line 1834, in full_dispatch_request
rv = self.handle_user_exception(e)
File "D:\PyCharm Projects\Plutone\lib\site-packages\flask\app.py", line 1737, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "D:\PyCharm Projects\Plutone\lib\site-packages\flask\_compat.py", line 36, in reraise
raise value
File "D:\PyCharm Projects\Plutone\lib\site-packages\flask\app.py", line 1832, in full_dispatch_request
rv = self.dispatch_request()
File "D:\PyCharm Projects\Plutone\lib\site-packages\flask\app.py", line 1818, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "D:\PyCharm Projects\Plutone\lib\site-packages\flask_dance\consumer\oauth2.py", line 271, in authorized
results = oauth_authorized.send(self, token=token) or []
File "D:\PyCharm Projects\Plutone\lib\site-packages\blinker\base.py", line 267, in send
for receiver in self.receivers_for(sender)]
File "D:\PyCharm Projects\Plutone\lib\site-packages\blinker\base.py", line 267, in <listcomp>
for receiver in self.receivers_for(sender)]
File "D:\PyCharm Projects\Plutone\app.py", line 129, in google_is_logged_in
query = User.query.filter_by(username=form.username.data)
NameError: name 'form' is not defined
127.0.0.1 - - [05/Aug/2019 20:54:05] "GET /google_login/google/authorized?state=U6S2e05D0wFNCcVSDNaZMgzYXIjrad&code=4%2FnQEU2cmc-ENix4_HvQP3t2jadQvXwFSGO2qw93w-Pr2ND_HnIAhDfVXWPGJBJHgFqlcoz6aIYid7o4_a1cJW1Zk&scope=email+profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+openid&authuser=0&session_state=8588e8ce3cddf3f4a89d8e65f56ce4a61b2fb901..f541&prompt=consent HTTP/1.1" 500 -
答案
Traceback说你必须在你的函数google_is_logged_in(blueprint,token)里面定义'form',就像你在142行做的那样。
以上是关于如何解决Flask登录中的谷歌登录问题?的主要内容,如果未能解决你的问题,请参考以下文章