简体   繁体   中英

Django + Tastypie - user_logged_in signal doesn't work

I have a Tastypie ModelResource defining various endpoints which work as expected.

I've now configured this ModelResource to have BasicAuthentication :

class Meta:
    authentication = BasicAuthentication()

I've defined a couple of test users through the Django Admin Interface.

As per the Django 1.7 Documentation , I've created a signals.py in which I register a couple of test signals:

from django.core.signals import request_finished
from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver

@receiver(user_logged_in)
def on_login(sender, request, user, **kwargs):
    print('******* LOGIN DETECTED *********')

@receiver(request_finished)
def on_request_finished(sender, **kwargs):
    print('******* REQUEST FINISHED *******')

This is loaded successfully by my AppConfig in apps.py :

from django.apps import AppConfig

class MyAppConfig(AppConfig):
    name = 'myapp'
    verbose_name = 'verbose description of myapp'

    def ready(self):
        import myapp.signals

I use the Requests library to successfully communicate with my API, providing basic authentication credentials for one of my test users:

auth = HTTPBasicAuth(username, getpass('Enter password: '))
response = requests.get(self.url(endpoint), auth=self.auth, params = params)

The REQUEST FINISHED print shows in the Django server's output, but LOGIN DETECTED does not.

Do we have to manually fire a login signal when using Tastypie, or use some other inbuilt/custom Authentication class besides BasicAuthentication ? In other words, is it expected that the user_logged_in signal wouldn't fire automatically?

Any info would be greatly appreciated.

Having inspected the Tastypie source code, it ties into the Django auth backend by calling the authenticate method, thus doesn't trigger the usual login cycle of which authenticate is one component. Consequently the login method is never called, and thus the user_logged_in signal never fires.

I ended up providing the signal myself by extending BasicAuthentication and overriding is_authenticated like so:

class MyBasicAuthentication(BasicAuthentication):
    def is_authenticated(self, request, **kwargs):
        orig_user = request.user
        has_authenticated = super(MyBasicAuthentication, self).is_authenticated(request, **kwargs)
        if has_authenticated:
            was_authenticated = orig_user == request.user
            if not was_authenticated:
                user_logged_in.send(sender=self.__class__, request=request, user=request.user)
        return has_authenticated

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