I have two types of Django servers. One is a central server that contains a master database. There's only one of these.
Then there's an arbitrary number of client servers that contain their own databases. These client databases act as a cache for the master database.
This is used for users. I a user tries to log in on client server 1, that server looks for the user in its database. If it's not there, it goes out to the central server and asks that server if the user exists in the master database. If so, the central server returns the users info so that the client server can store/cache it in its own database and then log the user in. Each successive time that user tries to log in, the user is found in the client database and it no longer has to go out to the central server.
The central server returns the users information as JSON like so:
{
"username": "joe.bag.o.doughnuts",
"id": 143,
"password": "fksdfjfldskjf",
}
My issue here is the password. when I put the value in there as just user.password, it uses the encrypted version of that password. This is good because I don't want the plain text password out there in http connections for security reasons. However, how do I store the encrypted password correctly when creating a copy of the user on the client server? If I set password to the encrypted text (User.objects.create(username=<retrieved_username>, password=<retrieved_password_which_is_already_encrypted>)), it will treat it as a plain text password and will then encrypt it... even though it's already encrypted so it's encrypting the encryption, not the actual password.
I wonder if you can achieve this a different way than by way of User.objects.create(...)? Depends on the server constraints, etc. but would this work for you?
From bash, maybe as cron job, something like this:
python manage.py dumpdata auth.users --indent 2 --natural-foreign --output users.json
Then load onto the other server using something like this:
python manage.py loaddata users.json
Or in the alternative, you might be able to create a custom user manager for the importation of users with previously hashed passwords:
from django.contrib.auth.base_user import BaseUserManager
class UserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email, password=password, **extra_fields)
# Normally here Django uses the set_password function
# https://docs.djangoproject.com/en/2.0/ref/contrib/auth/#django.contrib.auth.models.User.set_password
user.save(using=self._db)
return user
More info on extending/overriding User class here: https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html
Related
I still use the flask session manager for users. My config is like this:
app.config['SECRET_KEY'] = "mySecretKey"
app.config["SESSION_PERMANENT"] = True
app.config["SESSION_TYPE"] = "filesystem"
app.config['SESSION_USE_SIGNER'] = True
Whenever a user logs in a flask session file is created in the folder app\flask_session. It will be random alphanumeric file name, like 0609ece61011830ef9b6547217b9abd6.
the session file contains the email of the user. What I want to do is to delete a flask session file when a user resets their password, for security reasons. Like the user might have logged in to 5 devices and as the sessions don't expire the user gets to use the account on all 5 devices. But when the user changes the password, I need to delete all these 5 sessions which match the email id so that the user gets logged out on all the devices.
I am ready to loop through each session file. How can I achieve this?
you can use pickle package for that. Here is an example how to parse one of the session files:
import pickle
with open("sessions_dir/701dc705b498a6ee20475e5fcbcbdf99", "rb") as e:
time = pickle.load(e)
data = pickle.load(e)
print(time)
print(data)
You will need to get the email id from the data and act accordingly.
I have about 6 target databases with their own Django admin data and application data. Right now, I am running 6 instances of the same Django application on different hosts. What I would like to do is run one instance of the app, but up front have the user select which database he wishes to connect. Where should I inject this new code so that it hits BEFORE it tries to read the Django.core admin code?
I used the Django specified database for admin only, then a redirect gets the 'factory' specified database name. The handler for this redirect manually connects to the correct database. I now have 4 separate remote databases with a local administrative database. Django itself doesn't really handle this internally, so this is a workaround.
def login_view(request):
username = request.POST.get('username', '')
password = request.POST.get('password', '')
factory = request.POST.get('factory', '')
user = auth.authenticate(username=username, password=password)
if user is not None and user.is_active:
# Correct password, and the user is marked "active"
auth.login(request, user)
# Redirect to a success page.
return HttpResponseRedirect("/app/?factory={}".format(factory))
Given an username and password, I want to authenticate against a LDAP directoy with these credentials in one of my Django apps. I've been taking a look Django-auth-ldap but I still don't know how to use it properly once I've configured it.
On the one hand, I receive a JSON with username and password and I need to add an user to LDAP with these credentials. And, on the other hand, in subsequent request, I need to check that the user who makes the request belongs to LDAP (and only LDAP not the own Django backend, so if there's an user with the same credentials in the Django users database should't be allow to continue).
I've tried something like this to add an user:
authbackends.py
class CustomLDAPBackend(LDAPBackend):
def authenticate(self, username, password, **kwargs):
# Add user to LDAP
user = LDAPBackend.authenticate(self, username, password)
return user
So I can import it in my view to add the user to LDAP.
Could anyone outline a solution?
I am creating an inactive user and want to send them email for activating there accounts like the one django-registration send when we create an account.
This is my views.py
user = User.objects.create_user(userName, userMail,userPass)
user.is_active=False
user.save()
You should review the topical guide on sending emails. Basically, you'll just use the components from django.core.mail to send an activation email with all the necessary information after you've created the user instance.
It's important that that email contains further information on how the user is supposed to activate their account. The way django-registration does it is that it has a separate model associated with the User instance that specified a unique identifier which would be used in the activation view to identify which user account is supposed to be activated, i.e. creating a GET request to http://foo/accounts/activate/550e8400-e29b-41d4-a716-446655440000 would activate the user account with the associated UUID.
There are some other intricate details that make django-registration a thorough and well-polished solution, in spite of being a bit dated (i.e. no class-based views), so I second #NCao in suggesting that you take enough time to review the sources from the official repository and ripoff and duplicate all the necessary bits.
Basically after a user signed up, you want to set user.is_active=False.
Then you send an URL with the user's information(for example, id) to the user's email.
When the user click the link, it will trigger an activation function. Within the activation function, it firstly extracts the user's information based on the URL (id). Then you can query the user object by calling user.objects.get(id=id). After that, you can set user.is_active=True and save user.
Here is the code to send email:
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
fromaddr='your email address' #(Gmail here)
username='your user name'
password='your password'
def send_email(toaddr,id):
text = "Hi!\nHow are you?\nHere is the link to activate your
account:\nhttp://127.0.0.1:8000/register_activate/activation/?id=%s" %(id)
part1 = MIMEText(text, 'plain')
msg = MIMEMultipart('alternative')
msg.attach(part1)
subject="Activate your account "
msg="""\From: %s\nTo: %s\nSubject: %s\n\n%s""" % (fromaddr,toaddr,subject,msg.as_string())
#Use gmail's smtp server to send email. However, you need to turn on the setting "lesssecureapps" following this link:
#https://www.google.com/settings/security/lesssecureapps
server = smtplib.SMTP('smtp.gmail.com:587')
server.ehlo()
server.starttls()
server.login(username,password)
server.sendmail(fromaddr,[toaddr],msg)
server.quit()
You may also want to check this out: https://github.com/JunyiJ/django-register-activate
Hope it helps!
In my custom authentication backend I extract the username, email, first and last name from an LDAP response and try to stick them into a newly generated User object if the user doesn't yet exist:
user = User(username=username, email=result[0][1].get('mail')[0], first_name=result[0][1].get('givenName')[0], last_name=result[0][1].get('sn')[0])
user.save()
And another variant I tried:
user = User.objects.create_user(username, result[0][1].get('mail')[0])
user.first_name = result[0][1].get('givenName')[0]
user.last_name = result[0][1].get('sn')[0]
user.save()
While the username and email show up in the admin after the user's initial successful authentication attempt I can't get the first and last name to display. Logging the values from the LDAP response shows that these exist.
Any idea what's going wrong here?
Ok, it was indeed my own stupidity: should not only have restarted the frontend webserver but also uWSGI! I could add to my defense that these are my baby steps with uWSGI...