Djoser for DRF with Knox tokens

别来无恙 提交于 2021-02-19 05:21:28

问题


I'm trying to use djoser with token authentication, but using django-rest-knox tokens.

I have set the TOKEN_MODEL to knox.models.AuthToken, and the rest framework's DEFAULT_AUTHENTICATION_CLASSES to knox.auth.TokenAuthentication.

I naïvely thought that this would be enough, but it seems that Djoser's inbuilt serializers (create token, and token), don't work properly with the knox tokens. I tried overriding them with custom serializers, but I didn't get anywhere (which is not to say it's not possible, just that I'm bad at this).

It occurred to me that perhaps I should try using Knox's own login views... Is that possible, or can they not be mixed like that? (I'm mainly asking because I don't want to get it to 'work', but find that I've actually introduced a security hole in doing so).

Settings:

DJOSER = {
    "TOKEN_MODEL": "knox.models.AuthToken",
    "SERIALIZERS": {"token": "users.serializers.TokenSerializer"},
}

Where users.serializers.TokenSerializer is:

class TokenSerializer(serializers.ModelSerializer):
    auth_token = serializers.CharField(source="token_key")

    class Meta:
        model = settings.TOKEN_MODEL
        fields = ("auth_token",)

This is only slightly modified from the original Djoser TokenSerializer. It was throwing an error that AuthToken objects did not have a key attribute. Knox tokens seem to call it token_key, so I replaced the line: auth_token = serializers.CharField(source="key") with auth_token = serializers.CharField(source="token_key")

Now, it doesn't throw an error, but it returns an empty token. Inspecting the actual db shows that it has saved a token with the correct user and creation time, but with 'null' for digest, salt, and token_key


回答1:


Yes, it is possible to mixin's Djoser's and knox's additional view point. For that we are going to create an app name auth from where we are going to serve all authenticational related end-points. Now our project structure is like

MainProject
   -auth
      --__init__.py
      --urls.py
    -mainapp
    ....

Now in our auth app's urls we are going to serve our necessary end-points for authentication. For that we are going to take help from Djoser's urls link and Knox's urls link And our auth's urls.py will be like following

from django.conf.urls import url, include
from django.contrib.auth import get_user_model

from djoser import views as djsoer_views
from knox import views as knox_views

from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register('users', djsoer_views.UserViewSet)

User = get_user_model()

djoser_urlpatterns = [
    url(
        r'^users/create/?$',
        djsoer_views.UserCreateView.as_view(),
        name='user-create'
    ),
    url(
        r'^users/delete/?$',
        djsoer_views.UserDeleteView.as_view(),
        name='user-delete'
    ),
    url(
        r'^users/activate/?$',
        djsoer_views.ActivationView.as_view(),
        name='user-activate'
    ),
    url(
        r'^{0}/?$'.format(User.USERNAME_FIELD),
        djsoer_views.SetUsernameView.as_view(),
        name='set_username'
    ),
    url(r'^password/?$', djsoer_views.SetPasswordView.as_view(), name='set_password'),
    url(
        r'^password/reset/?$',
        djsoer_views.PasswordResetView.as_view(),
        name='password_reset'
    ),
    url(
        r'^password/reset/confirm/?$',
        djsoer_views.PasswordResetConfirmView.as_view(),
        name='password_reset_confirm'
    ),
    url(r'^$', djsoer_views.RootView.as_view(), name='root'),
    url(r'^', include(router.urls)),   ### If you want to add user view set
]

knox_urlpatterns = [
    url(r'login/', knox_views.LoginView.as_view(), name='knox_login'),
    url(r'logout/', knox_views.LogoutView.as_view(), name='knox_logout'),
    url(r'logoutall/', knox_views.LogoutAllView.as_view(), name='knox_logoutall'),
]

urlpatterns = knox_urlpatterns + djoser_urlpatterns

Now we are going to add this urls under our main_app's urls

from django.urls import path
from django.conf import settings
auth_urls = include('auth.urls')

urlpatterns = [
    path('api/auth/', auth_urls),
    ......

]

Now we are going to able to access every end-point like login as api/auth/login/ or user-create as api/auth/user/create/ etc.

What i can see that djoser add some additional UserViewset end-point by default mostly you may not like this , you should include what is really needed for you.

来源:https://stackoverflow.com/questions/54960669/djoser-for-drf-with-knox-tokens

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!