无法通过Requests-OAuthlib构建Google OAuth2与Flask一起使用

如何解决无法通过Requests-OAuthlib构建Google OAuth2与Flask一起使用

我尝试使用flask登录构建gooogle登录。 我在这里找到线程 Using Google OAuth2 with Flask

我能够移植接受的答案以使用Requests-OAuthlib而不是Rauth。在撰写本文时,该软件包的最后一次提交是在2019年6月,当前已被30K +存储库使用。

初始 .py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
import dir
from flask_mail import Mail

# init SQLAlchemy so we can use it later in our models
db = SQLAlchemy()
mail = Mail()

GOOGLE_LOGIN_CLIENT_ID = "mygoogle API id .apps.googleusercontent.com" #I am sure It is correct
GOOGLE_LOGIN_CLIENT_SECRET = "my_secret_key"
def create_app():
    app = Flask(__name__)
    app.debug = True
    app.config['SECRET_KEY'] = 'secret-key-goes-here'

    # app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////' + str(dir.dir) + '/admin.sqlite'
    app.config['MAIL_SERVER'] = 'smtp.gmail.com'
    app.config['MAIL_PORT'] = 465
    app.config['MAIL_USERNAME'] = 'ruaxe.sdafsafsafs'
    app.config['MAIL_PASSWORD'] = 'uiykejafsaffiqklziccld'
    app.config['MAIL_USE_TLS'] = False
    app.config['MAIL_USE_SSL'] = True
    app.config['OAUTH_CREDENTIALS']  = {
        'google': {
            'id': GOOGLE_LOGIN_CLIENT_ID,'secret': GOOGLE_LOGIN_CLIENT_SECRET
        }
    }
    mail.init_app(app)
    db.init_app(app)
    with app.app_context():
        db.create_all()

    login_manager = LoginManager()
    login_manager.login_view = 'auth.login'
    login_manager.init_app(app)
    from .models import User
    @login_manager.user_loader
    def load_user(user_id):
        # since the user_id is just the primary key of our user table,use it in the query for the user
        return User.query.get(int(user_id))



    # blueprint for auth routes in our app
    from .auth import auth as auth_blueprint
    app.register_blueprint(auth_blueprint)

    # blueprint for non-auth parts of app
    from .main import main as main_blueprint
    app.register_blueprint(main_blueprint)


    return app


然后我用登录页面构建auth.py

auth = Blueprint('auth',__name__)

@auth.route('/login',methods=['GET'])
def login():
    if current_user is not None and current_user.is_authenticated:
        return redirect(url_for('main.index'))
    return render_template('login.html')

我在main.py中构建的用户查看页面

from __future__ import print_function
from flask import Blueprint,render_template,request,redirect,flash,url_for,current_app
from flask_login import login_required,current_user,login_user
from project.function import cmsHaravan as hara,cmsCalendar as cal
from .function import config as cf,cmsContacts as ct
from datetime import datetime,timedelta,date
from .models import User,Order,Shop
from . import db,mail
from flask_mail import Message
import random
import string
from werkzeug.security import generate_password_hash
import json
from requests_oauthlib import OAuth2Session
from urllib.request import urlopen

main = Blueprint('main',__name__)

class OAuthSignIn(object):
    providers = None

    def __init__(self,provider_name):
        self.provider_name = provider_name
        credentials = current_app.config['OAUTH_CREDENTIALS'][provider_name]
        self.consumer_id = credentials['id']
        self.consumer_secret = credentials['secret']

    def authorize(self):
        pass

    def callback(self):
        pass

    def get_callback_url(self):
        return url_for('main.profile',provider=self.provider_name,_external=True)

    @classmethod
    def get_provider(self,provider_name):
        if self.providers is None:
            self.providers={}
            for provider_class in self.__subclasses__():
                provider = provider_class()
                self.providers[provider.provider_name] = provider
        return self.providers[provider_name]

class GoogleSignIn(OAuthSignIn):
    openid_url = "https://accounts.google.com/.well-known/openid-configuration"
    def __init__(self):
        super(GoogleSignIn,self).__init__("google")
        self.openid_config = json.load(urlopen(self.openid_url))
        self.session = OAuth2Session(
            client_id=self.consumer_id,redirect_uri=self.get_callback_url(),scope=self.openid_config["scopes_supported"]
        )

    def authorize(self):
        auth_url,_ = self.session.authorization_url(
            self.openid_config["authorization_endpoint"])
        print(auth_url)
        return redirect(auth_url)

    def callback(self):
        if "code" not in request.args:
            return None,None

        self.session.fetch_token(
            token_url=self.openid_config["token_endpoint"],code=request.args["code"],client_secret=self.consumer_secret,)

        me = self.session.get(self.openid_config["userinfo_endpoint"]).json()
        print(me)
        print(me["name"],me["email"])
        return me["name"],me["email"]
@main.route('/authorize/<provider>')
def oauth_authorize(provider):
    # Flask-Login function
    if not current_user.is_anonymous:
        return redirect(url_for('index'))
    oauth = OAuthSignIn.get_provider(provider)
    return oauth.authorize()

@main.route('/profile/<provider>')
def oauth_callback(provider):
    if not current_user.is_anonymous:
        return redirect(url_for('main.index'))
    oauth = OAuthSignIn.get_provider(provider)
    name,email = oauth.callback()
    print("da lay duoc email",email)
    if email is None:
        # I need a valid email address for my user identification
        flash('Authentication failed.')
        return redirect(url_for('auth.login'))
    # Look if the user already exists
    user=User.query.filter_by(email=email).first()
    if not user:
        # Create the user. Try and use their name returned by Google,# but if it is not set,split the email address at the @.
        name = name
        if name is None or name == "":
            name = email.split('@')[0]

        # We can do more work here to ensure a unique nickname,if you
        # require that.
        user=User(firstname=name,email=email)
        db.session.add(user)
        db.session.commit()
    # Log in the user,by default remembering them for their next visit
    # unless they log out.
    login_user(user,remember=True)
    return redirect(url_for('main.index'))


@main.route('/profile')
@login_required
def profile():
    ListCarBrands = cal.getListCarBrands()
    ListProvinces = cal.getListProvinces()
    order_email = current_user.email
    list_order = {}
    i = 0
    for row in Order.query.filter_by(order_email=order_email):
        i = i + 1
        total_order = i
        list_order[i] = row.__dict__
    return render_template('profile.html',list_order=list_order,name=current_user.lastname,biensoxe=current_user.biensoxe,ListCarBrands=ListCarBrands,brands=current_user.brands,carclass=current_user.carclass,firstname=current_user.firstname,lastname=current_user.lastname,phone=current_user.phone,email=current_user.email,ListProvinces=ListProvinces,provinces=current_user.provinces)

login.html

{% extends "base.html" %}

{% block content %}
     <div id="sign-in">
        <h1>Sign In</h1>
        <p>
        <a href={{ url_for('main.oauth_authorize',provider='google') }}><img src="{{ url_for('static',filename='img/sign-in-with-google.png') }}" /></a>
    </div>

    <form method="POST" action="/login">
        <div class="ui-information-body">
            <div class="align-content-center">
                {% with messages = get_flashed_messages() %}
                    {% if messages %}
                        <div class="notification is-danger">
                            {{ messages[0] }}
                        </div>
                    {% endif %}
                {% endwith %}
                <h4>Login {{ error }}</h4>
                <div class="row">
                    <div class="col-5 "><label class="label-input-group">Email </label><input type="email"
                                                                                              class="next-input"
                                                                                              name="email" id="email"
                                                                                              value=""></div>
                </div>
                <div class="row">

                    <div class="col-5 "><label class="label-input-group">Password</label><input type="password"
                                                                                                class="next-input"
                                                                                                name="password"
                                                                                                id="password"
                                                                                                value=""></div>


                </div>
                <div class="row">
                    <div class="col-5 "><span class="label-input-group"><br></span>
                        <a href="{{ url_for('main.reset_password') }}" class="btn btn-danger btn-lg btn-block">
                            Nếu bạn quên mật khẩu? Reset
                        </a></div>


                </div>
                <div class="row">
                    <div class="col-5 "><span class="label-input-group"><br></span><input
                            class="btn btn-primary btn-lg btn-block" type="submit" value="Login"></div>

                </div>

            </div>


        </div>
        </div>
    </form>
{% endblock %}

个人资料html

{% extends "base.html" %}
{% block content %}
    <form method="POST" action="/profile">
        Some code here for user can update profile
    </form>
    </div>


{% endblock %}

然后我运行程序,我可以将链接作为代码获取

    def authorize(self):
        auth_url,_ = self.session.authorization_url(
            self.openid_config["authorization_endpoint"])
        print(auth_url) ##### This function run
        return redirect(auth_url)
https://accounts.google.com/o/oauth2/v2/auth?response_type=code&client_id=880298757050-ij79mostsm1fccdcvuj43m0oe0quisih.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fprofile%3Fprovider%3Dgoogle&scope=openid+email+profile&state=xwbrUEpMjhIFrM6l3PlXgcXdgzyDbd
127.0.0.1 - - [21/Aug/2020 14:03:32] "GET /authorize/google HTTP/1.1" 302 -
127.0.0.1 - - [21/Aug/2020 14:03:35] "GET /profile?provider=google&state=xwbrUEpMjhIFrM6l3PlXgcXdgzyDbd&code=4%2F3QFTG6I2FzBPUKD_Sk0hq4IUhlr0jA4EQ2fTLyQizyYsPkCLxRf_WXwQz929v4wUeJhN4IXWFWu7nLKBJ2NHhog&scope=email+profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&authuser=0&prompt=consent HTTP/1.1" 302 -
127.0.0.1 - - [21/Aug/2020 14:03:35] "GET /login?next=%2Fprofile%3Fprovider%3Dgoogle%26state%3DxwbrUEpMjhIFrM6l3PlXgcXdgzyDbd%26code%3D4%252F3QFTG6I2FzBPUKD_Sk0hq4IUhlr0jA4EQ2fTLyQizyYsPkCLxRf_WXwQz929v4wUeJhN4IXWFWu7nLKBJ2NHhog%26scope%3Demail%2Bprofile%2Bopenid%2Bhttps%253A%252F%252Fwww.googleapis.com%252Fauth%252Fuserinfo.email%2Bhttps%253A%252F%252Fwww.googleapis.com%252Fauth%252Fuserinfo.profile%26authuser%3D0%26prompt%3Dconsent HTTP/1.1" 200 -
127.0.0.1 - - [21/Aug/2020 14:03:35] "GET /static/img/sign-in-with-google.png HTTP/1.1" 404 -
127.0.0.1 - - [21/Aug/2020 14:03:35] "GET /static/css/bootstrap.js HTTP/1.1" 404 -

但是我尝试将电子邮件作为路线资料中的代码打印

oauth = OAuthSignIn.get_provider(provider)
    name,email)

一无所有!所以任何人都可以帮助我 感谢所有人

解决方法

谢谢大家 我更改范围并运行!

class GoogleSignIn(OAuthSignIn):
    openid_url = "https://accounts.google.com/.well-known/openid-configuration"
    def __init__(self):
        super(GoogleSignIn,self).__init__("google")
        self.openid_config = json.load(urlopen(self.openid_url))
        self.session = OAuth2Session(
            client_id=self.consumer_id,redirect_uri=self.get_callback_url(),scope='https://www.googleapis.com/auth/userinfo.profile openid https://www.googleapis.com/auth/userinfo.email'
        )

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-