Google app engine task queue and users service

2019-07-21 06:40发布

问题:

I am using python and Google app engine. I would like to use the task queue. As part of the task queue handler I check if the current user is an admin (using the Users service). This test always fails. Is there a way to cause this test to pass?

update: To avoid further confusion, I am trying to find if the user that triggered the task was an admin or not (this is just a simple example). I understand that the task is being run from the server and all the users cookies are long gone. So the answer I was hopping for was a way to transfer the session to the task

import logging
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import taskqueue

class MyRequesHandler(webapp.RequestHandler):
    def get(self):
        taskqueue.add(url="/task/")

class MyTaskHandler(webapp.RequestHandler):
    def post(self):
        if users.is_current_user_admin():
            logging.debug("admin")
        else:
            logging.debug("not admin")


def main():
    logging.getLogger().setLevel(logging.DEBUG)
    application = webapp.WSGIApplication([
            ('/', MyRequesHandler),
            ('/task/', MyTaskHandler)
        ],
        debug=True)
    run_wsgi_app(application)

回答1:

The Users API reflects the details of the logged in user for the current request, and obviously in the case of a task queue task, there is no user, since it's initiated by the task queue system. You'll need to perform this check before you enqueue the task, and pass the result as a flag to the task, instead.



回答2:

To have the task being executed on behalf on some particular, just transfer the datastore ID or key (or any other identifier of the user) to the task as its payload.

class MyRequesHandler(webapp.RequestHandler):
    def get(self):
        taskqueue.add(url="/task/do_something", params={'user_email': users.get_current_user().email()})

class MyTaskHandler(webapp.RequestHandler):
    def post(self):
        user_email = self.request.POST.get('user_email')
        user = User.all().filter('email', user_email).get()
        # ... do something on behalf of user

This would obviously require protecting the task's URL from external unauthorized access -- this can be done in app.yaml:

handlers:
    - url: /task/(.*)
      script: tasks.py
      login: admin

Taskqueue has no problem accessing URLs that require admin login.



回答3:

The originating user is not available through the users service when executing task queue items. However, when creating a task, you can include the original user's ID as part of the request.

To prevent external users from falsifying this user ID during task execution, look for the X-AppEngine-QueueName request header. This header is only present on task queue items and cannot be faked by external users.