简体   繁体   中英

Django send authenticated user to another django server with the same db

I know question sounds strange, I will explain it here. I have two Django servers which share the same DB. One is a light front/back server and the order one takes the heavy computing part. They share the same database. I am currently securing the web, and I have a couple of views in the light server requiring user login:

@login_required() 
@permission_required('auth.can_upload', login_url='/accounts/login/')

This works nicely in the light server since the user is authenticated (request.user returns a valid user in the views).

The problem comes when I have to send the uploaded data to the other server since it is protected as I showed earlier, I do not know how to pass it the user that is already logged (user is valid since servers share the DB).

# send an upload request using requests
s = requests.Session()

r1 = s.get(upload_process_url)
csrf_token = r1.cookies['csrftoken']
a = s.post(upload_process_url, files=request.FILES,
                   data={'csrfmiddlewaretoken': csrf_token},
                   headers=dict(Referer=upload_process_url))

I cannot ask every time the user and password or save them. The thing is I want to pass the user that is already logged in a request.
The user was logged using the default django accounts/login page and authentication.

Any clues and what could I try? I think this problem cannot be as difficult as it looks to me. I just want to send an authenticated request. If I remove the decorators everything works nicely with this code

Thanks a lot

Have a look at REMOTE_USER authentication :

This document describes how to make use of external authentication sources (where the Web server sets the REMOTE_USER environment variable) in your Django applications. This type of authentication solution is typically seen on intranet sites, with single sign-on solutions such as IIS and Integrated Windows Authentication or Apache and mod_authnz_ldap, CAS, Cosign, WebAuth, mod_auth_sspi, etc.

Basically your "light" server does the authentication as it already does. When you are doing a request to your "heavy" server, you should set a Auth-User header containing the username of your user. Django will then automatically authenticates the corresponding user.

By default, Django will read an environment variable set by an authentication server. But we can make it work with a HTTP header instead:

# middlewares.py

from django.contrib.auth.middleware import RemoteUserMiddleware

class CustomHeaderMiddleware(RemoteUserMiddleware):
    header = 'HTTP_AUTH_USER'
# settings.py

MIDDLEWARE = [
    '...',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'my_project.middlewares.CustomHeaderMiddleware',
    '...',
]

Then, you can do something like this then in your request (assuming you have your Django user at hand):

s = requests.Session()

r1 = s.get(upload_process_url)
a = s.post(
    upload_process_url,
    files=request.FILES,
    headers={
        'Auth-User': user.username,
    },
)

Since you're not doing a request from a browser, you can avoid the CSRF protection by marking the called "heavy" view with @csrf_exempt decorator (as you found yourself).

Be careful though that your "heavy" server should not be accessible directly on the internet and always behind a proxy/VPN accessible only by your "light" server.

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