简体   繁体   中英

Flask-Login, Session Management and AJAX

I'm having trouble getting an AJAX call to work with the Flask-Login current_user object and the @login_required decorator. I believe it has something to do with the session not being passed.

The goal is for a user to click on a link that makes an AJAX call to a route URL that will provide a SSO session ID through a SOAP service. The SOAP service requires an emp_id to be passed which can be accessed through the current_user.emp_id attribute.

I initially attempted the AJAX call without the @login_required decorator and just passing a simple message as such which returned successfully:

app.js

const ssoLinks = document.querySelectorAll('.sso');

ssoLinks.forEach((ssoLink) => {
  ssoLink.addEventListener('click', (e) => generateSSOLink(e, ssoLink.id));
});


function generateSSOLink(e, page) {
  e.preventDefault();

  fetch("/get_bpm_sso_link")
    .then(response => response.json())
    .then(data => console.log(data))
}

views.py

@app.route('/get_bpm_sso_link')
def get_bpm_sso_link():
    data = {
        'msg': 'success'
    }

    print('*'*75)
    print('SUCCESS')
    print('*'*75)

    return jsonify(data)

My next attempt was to access the emp_id in current_user :

views.py

@app.route('/get_bpm_sso_link')
def get_bpm_sso_link():
    data = {
        'msg': 'success'
    }

    print('*'*75)
    print(current_user.emp_id)
    print('*'*75)

    return jsonify(data)

Which gave me this error:

AttributeError: 'AnonymousUserMixin' object has no attribute 'emp_id'

Okay, so then I decided to try and access the same emp_id attribute on the initial index page(where the AJAX lives as well) and was able to do so. It sounds like during an AJAX request, the Flask-Login LoginManager doesn't recognize the session of the current_user . To further this claim, I added the @login_required decorator to the route and the JSON response returned a redirect to the login page.

What can I do to have Flask-Login recognize a user during an AJAX call? If not, what other libraries can handle user session management and AJAX requests seamlessly?

So I did some digging this week at Pycon 2018 in Cleveland and came across a noteworthy topic regarding the Fetch API. Seems by default that the API doesn't send any user credentials. To remedy this, it all came down to setting an option within the API:

app.js

function generateSSOLink(e, page) {
  e.preventDefault();

  fetch("/get_bpm_sso_link", {
    credentials: 'include'
  })
    .then(response => response.json())
    .then(data => console.log(data))
}

Now my AJAX request hits my view even with the @login_required decorator.

What you need is to login using request loader as per this example on flask for each request

And probably disable setting the Flask Session cookie

Then Using fetch add headers with basic authentication

    fetch('/get_bpm_sso_link', { 
    method: 'get', 
    //or whichever method you are using
    headers: new Headers({
     'Authorization': 'Basic '+btoa('username:password') 
     //btoa base64 encodes your credentials, the flask example above shows how to decode
     })
 });

Ideally because the credentials are not hashed, they should be passed over https in production

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM