如何在重定向后跟踪烧瓶会话?

时间:2017-05-30 18:25:47

标签: python flask webdriver phantomjs

我正在Flask中编写一个webapp,我正在从用户那里获取表单数据。在他们传递了这些数据之后,我正在尝试使用amazon自动化身份验证。

  1. 所以我发送了一个带有查询字符串的GET,亚马逊向我发送了他们的登录页面

  2. 用户可以使用他们的亚马逊帐户登录,但我正在尝试使用selenium python webdriver自动将其记录在他们首先提交的信息中。

  3. 使用webdriver登录后,Amazon会重定向到我通过初始查询字符串传入的URL。重定向的URL现在有一个访问代码,我需要抓取并将其用作令牌身份验证过程的一部分。

  4. 这是问题所在: 在最后一次重定向之后,我的Flask应用程序丢失了我存储在会话cookie中的所有内容。我的目的是使用会话来跟踪user_id,以便我可以使用检索到的访问代码更新用户记录。

    那么在重定向到外部登录站点后,如何在Flask中丢失会话?

    更新(代码示例):

    @app.route('/index', methods=['GET', 'POST'])
    def index():
    
        if request.method == 'POST:
            # user is logged in and added to database here
            configs = request.files['config']
            session_id = b64encode(os.urandom(24))
            session['user_config'] = configs
            session['session_id'] = session_id
    
            user = User.query.filter_by(email=configs['email']).first()
            if user is None:
                # add user to database with data in configs dict file
                # ...
                return redirect(url_for("app.get_auth_code"))
            else:
                # no need to authenticate user
                # continue work as expected
                # ...
    
    
    
    @app.route('/lwa', methods=['GET', 'POST'])
    @login_required
    def get_auth_code():
    
        auth_url = "https://www.amazon.com/ap/oa"
        redirect_uri = "http://localhost:5000" +  url_for("app.authresponse")
    
        sd = json.dumps({
            "alexa:all": {
                "productID": session['user_config']['DEVICE_TYPE_ID'],
                "productInstanceAttributes": {
                    "deviceSerialNumber": "001"
                }
            }
        })
        payload = {
            "client_id": session['user_config']['CLIENT_ID'],
            "scope": "alexa:all",
            "scope_data": sd,
            "response_type": "code",
            "redirect_uri": redirect_uri
        }
    
        query_str = "?" + urlencode(payload, doseq=True)
        driver = webdriver.Firefox(executable_path='/tmp/geckodriver')
        driver.get(auth_url + query_str)
    
        wait = WebDriverWait(driver, 10)
        amazon_sign_in = wait.until(EC.title_contains("Amazon.com Sign In"))
    
        if amazon_sign_in:
            username = driver.find_element_by_id('ap_email')
            password = driver.find_element_by_id('ap_password')
            submit_button = driver.find_element_by_id("signInSubmit")
    
            # Fill in email and password
            username.send_keys(session['user_config']['EMAIL'])
            password.send_keys(session['user_config']['PASSWORD'])
            submit_button.click()
            # driver.close()
            return redirect(url_for("app.authresponse"))
        else:
            flash("Login With Amazon page not found")
            return redirect(url_for("app.index"))
    
        return redirect(url_for("app.index"))
    
    
    ## This is the function where I lose the session for the same user  
    ## This is the callback route that amazon sends the auth code to after the user is logged in
    @app.route('/authresponse', methods=['GET', 'POST'])
    def authresponse():
        code = None
        if request.method == 'GET':
            code = request.args.get('code', None)
            if code:
                user = User.query.filter_by(session_id=session.get("session_id")).first()
    
                if user:
                    user.auth_code = code
                    db.session.commit()
    
                    # retrieve access token with POST request
                    url = "https://api.amazon.com/auth/o2/token"
                    payload = {
                        "client_id": user.client_id,
                        "client_secret": user.client_secret,
                        "code": code,
                        "grant_type": "authorization_code",
                        "redirect_uri": "http://localhost:5000" + url_for("app.authresponse")
                    }
                    r = requests.post(url, data=payload, timeout=5)
                    if r.status_code == 200:
                        print r.text
                        return r.text
                    else:
                        print r.text, r.status_code
                else:
                    print "User not found"
                    flash("Auth code not found.")
    
        return """code:<div id="token">{}</div>""".format(code)
    

1 个答案:

答案 0 :(得分:0)

我向亚马逊发出Oauth2请求时,找到了一个解决方案,让用户的信息在不同的页面之间保持不变。我假设其他网站的身份验证过程非常相似,所以我添加了我使用的解决方案。

  1. 创建会话ID并存储在数据库或缓存中
  2. 通过“州”字段将OAuth2请求的状态传递到您的有效负载中,将状态指定为会话ID

    if(this.props.someProp !== nextProps.someProp) {
        // call some function only when the prop has changed
    }
    
  3. 在身份验证服务发送访问令牌的重定向网址中,STATE应出现在重定向URI的查询字符串中。

  4. 从查询字符串中获取STATE并使用它从数据库或缓存中获取所需的所有用户信息。

  5. 亚马逊解决方案:

    1. https://developer.amazon.com/public/apis/engage/login-with-amazon/docs/dynamically_redirect_users.html

    2. https://developer.amazon.com/public/apis/engage/login-with-amazon/docs/cross_site_request_forgery.html