Python 如何解决InvalidClientError(oauthlib.oauth2)

Python 如何解决InvalidClientError(oauthlib.oauth2),python,flask,google-signin,flask-oauthlib,Python,Flask,Google Signin,Flask Oauthlib,我目前正在尝试将Google登录功能集成到我的本地Flask Web应用程序中,并使用OAuthlib。如图所示,在尝试运行Flask Google登录功能的完成实现时,我遇到了以下错误: oauthlib.oauth2.rfc6749.errors.InvalidClientError:(无效的客户端)未经授权 它指向我的routes.py文件中的这一行代码: client.parse\u request\u body\u response(json.dumps(token\u respons

我目前正在尝试将Google登录功能集成到我的本地Flask Web应用程序中,并使用OAuthlib。如图所示,在尝试运行Flask Google登录功能的完成实现时,我遇到了以下错误:

oauthlib.oauth2.rfc6749.errors.InvalidClientError:(无效的客户端)未经授权

它指向我的
routes.py
文件中的这一行代码:

client.parse\u request\u body\u response(json.dumps(token\u response.json()))
我不知道为什么会出现这个错误,我该如何解决这个问题

以下是我的
app/\uuuuu init\uuuuuuuuupy
文件和
routes.py
文件中的示例:

app/\uuuu init\uuuu.py

导入操作系统
从烧瓶进口烧瓶
从配置导入开发
从缓存导入缓存
从登录导入登录管理器
从flask_sqlalchemy导入sqlalchemy
从oauthlib.oauth2导入WebApplicationClient
app=烧瓶(名称)
app.config.from_对象(开发)
缓存=缓存(应用程序)
db=SQLAlchemy(应用程序)
login\u manager=LoginManager()
登录管理器。初始化应用程序(应用程序)
os.environ['OAUTHLIB\u unsecure\u TRANSPORT']=“1”
GOOGLE\u CLIENT\u ID=os.getenv(“GOOGLE\u CLIENT\u ID”)
client=WebApplicationClient(GOOGLE\u client\u ID)
从应用程序导入路由、表单、登录、模型

app/routes.py

导入操作系统
...
GOOGLE\u CLIENT\u ID=os.getenv(“GOOGLE\u CLIENT\u ID”)
GOOGLE\u CLIENT\u SECRET=os.getenv(“GOOGLE\u CLIENT\u SECRET”)
谷歌搜索搜索URL=(
"https://accounts.google.com/.well-known/openid-configuration"
)
def get_google_provider_cfg():
returnrequests.get(GOOGLE\u DISCOVERY\u URL).json()
...
@app.route(“/login google”)
def login_google():
google\u provider\u cfg=get\u google\u provider\u cfg()
授权\端点=谷歌\提供商\ cfg[“授权\端点”]
request\u uri=client.prepare\u request\u uri(
授权(U)端点,
重定向_uri=flask.request.base_url+'/callback',
范围=[“openid”、“电子邮件”、“配置文件”],
)
返回烧瓶。重定向(请求\u uri)
@app.route(“/login google/callback”)
def callback():
代码=flask.request.args.get(“代码”)
google\u provider\u cfg=get\u google\u provider\u cfg()
token\u endpoint=google\u provider\u cfg[“token\u endpoint”]
令牌\u url,标题,正文=客户端。准备令牌\u请求(
令牌\端点,授权\响应=flask.request.url,
重定向\u url=flask.request.base\u url,代码=code
)
令牌\响应=requests.post(
token_url,headers=headers,
data=body,auth=(GOOGLE\u CLIENT\u ID,GOOGLE\u CLIENT\u SECRET),
)

client.parse_request_body_response(json.dumps(token_response.json())##你是说你想让谷歌登录到你的网站? 我有自己的代码,它工作得很好 首先,init.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 = "xxxxxxxx-xxxxxxxxx.apps.googleusercontent.com"
GOOGLE_LOGIN_CLIENT_SECRET = "xxxxxxxxx"
def create_app():
    app = Flask(__name__)
    app.debug = False
    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' #this is dabase, you can change it.
    app.config['MAIL_SERVER'] = 'smtp.gmail.com'
    app.config['MAIL_PORT'] = 465
    app.config['MAIL_USERNAME'] = 'youremail@gmail.com'
    app.config['MAIL_PASSWORD'] = 'yourpass'
    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)

    from .serv import serv as serv_blueprint
    app.register_blueprint(serv_blueprint)

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

    from .search import search as sear_blueprint
    app.register_blueprint(sear_blueprint)

    from .dash import dash as dash_blueprint
    app.register_blueprint(dash_blueprint)

    from .dlf import dlf as dlf_blueprint
    app.register_blueprint(dlf_blueprint)

    from .contact import contact as contact_blueprint
    app.register_blueprint(contact_blueprint)


    return app


第二,在main.py中,您可以更改为app.py,为便于将来编写代码,我认为您应该使用


要使用模型,我使用

谢谢!我已经修改了一些代码以反映您的代码,问题似乎是请求是通过HTTP而不是HTTPS进行的(尽管我无法理解为什么没有得到该错误),这很有帮助=DGoogle支持不带https的localhost,您可以试试
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, Orders, Shop, Services
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
import dateutil
from oauth2client.client import OAuth2WebServerFlow
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.oauth_callback', 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='https://www.googleapis.com/auth/userinfo.profile openid https://www.googleapis.com/auth/userinfo.email '
        )

    def authorize(self):
        auth_url, _ = self.session.authorization_url(
            self.openid_config["authorization_endpoint"])
        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)
        return me["family_name"], me["given_name"], me["email"], me["picture"]


@main.route('/authorize/<provider>')
def oauth_authorize(provider):
    # Flask-Login function
    if not current_user.is_anonymous:
        return redirect(url_for('main.index'))
    oauth = OAuthSignIn.get_provider(provider)
    return oauth.authorize()


@main.route('/callback/<provider>')
def oauth_callback(provider):
    if not current_user.is_anonymous:
        return redirect(url_for('main.index'))
    oauth = OAuthSignIn.get_provider(provider)
    flamily_name, given_name, email, avatar = oauth.callback()
    print("Successfull to get email", email)
    if email is None:
        # I need a valid email address for my user identification
        flash('Invalid')
        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 = given_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=given_name, lastname=name, email=email, avatar=avatar)
        db.session.add(user)
        db.session.commit()
    # Log in the user, by default remembering them for their next visit
    # unless they log out.
    user.firstname = flamily_name
    user.lastname = given_name
    user.avatar = avatar
    db.session.commit()
    login_user(user, remember=True)
    return redirect(url_for('main.profile'))
<div class="row">
                <div class="col "><span class="label-input-group"><br></span>
                    <a href="{{ url_for('main.oauth_authorize', provider='google') }}" class="btn btn-light btn-lg btn-block border-primary text-primary">
                        Login with google with out password
                    </a>
                </div>


            </div>
from flask_login import UserMixin
from . import db
from datetime import datetime, timedelta, date
class User(UserMixin, db.Model):
    __tablename__ = 'user'
    id = db.Column(db.Integer, primary_key=True)  # primary keys are required by SQLAlchemy
    firstname = db.Column(db.String(30))
    lastname = db.Column(db.String(30))
    email = db.Column(db.String(100), unique=True)
    phone = db.Column(db.String(10))
    password = db.Column(db.String(20))