问题
I'd like to setup an LDAP Authentication Backend in Django, and I've already used ldap3
to confirm a bind, with success.
I'm now realising that writing a class for my LDAP Backend with just ldap3
is not so straightforward, and that installing
django_auth_ldap
could be another route to explore.
I've tested already some code to create a bind to the LDAP "server", and then perform a simple search. All okay. This method I tested is outside of my Django framework.
When implementing the same method into my Django framework, I encounter an issue when the method gets called. Because of the print statements, I know the view
is getting called as exptected, but the part of the code whereby the first "if" statement should be executed, does not get called unless I change from "POST"
to "GET". But then this seems to create the next issue (when I set to "GET", so to force the next lines to be executed), because I'd like that a login page then gets called, where I can then input my LDAP credentials,
ultimately confirming the LDAP connection. Here is my code:
views.py
def login_ldap(request):
LDAP_SERVER = '10.222.4.88'
searchFilter='random'
print (request)
print (LDAP_SERVER)
print ("request.method:{0}".format(request.method))
if request.method == "GET":
print ("if statement executed")
username = request.GET['username']
print ("U:{0}".format(username))
password = request.GET['password']
print ("P:{0}".format(password))
# Define the server and bind_dn
server = Server(LDAP_SERVER, get_info=ALL)
bind_dn = 'cn={0}, ou=Prod, ou=Extern, ou=User, ou=ABC, dc=DEF, dc=com'.format(username)
# Define the Connection
conn = Connection(server, bind_dn, password, auto_bind=True) # Use raise_exceptions=True for exceptions
print ("search: {0}",format(conn.search))
print ("conn: {0}",format(conn))
conn.start_tls() #Session now on a secure channel. See output from following print statement and "tls started"
print ("conn_tls: {0}",format(conn))
d = conn.extend.standard.who_am_i()
print (d)
#print ("Server Info: {0}",format(server.info))
conn.open()
conn.bind()
# The LDAP search base for looking up users.
LDAP_AUTH_SEARCH_BASE = "ou=ABC, dc=DEF, dc=com"
if conn.bind():
conn.search(
search_base=LDAP_AUTH_SEARCH_BASE,
search_filter= '(cn={})'.format(searchFilter), # This is the user being searched for
search_scope=SUBTREE # BASE & LEVEL also possible settings
)
entry = conn.entries[0]
res = conn.bind()
print (res)
return render(request, 'search_page.html', {'entry':entry})
The error message received on my webpage:
MultiValueDictKeyError at /login_ldap/
"'username'"
Request Method: GET
Request URL: http://127.0.0.1:8000/login_ldap/
Django Version: 1.11
Exception Type: MultiValueDictKeyError
Exception Value:
"'username'"
I assume this is related to the GET and no longer the POST method. Why is the request.method
being automatically set to GET and not POST when implementing
this in Django? Is this class for the authentication in the correct location, in the views.py
file or should there be a separate file for this?
What should be included in the settings.py
exactly (related to BACKEND_AUTH)?
EDIT:
views.py
def login_view(request):
if request.POST:
username = request.POST['username']
print ("U:{0}".format(username))
password = request.POST['password']
print ("P:{0}".format(password))
user = authenticate(username=username, password=password)
print (user)
if user is not None:
if user.is_active:
login(request, user)
return redirect('index')
else:
messages.error(request, "User is not active in Database")
else:
print ("Please check your credentials!")
messages.error(request, "Please check your username and password!")
return render(request, 'login.html')
index.html
<div class="row">
<div class="col-lg-3"></div>
<div class="col-lg-6"><H1>This is the public page, Please <a href="{% url 'login_ldap' %}">Login</a></H1></div>
</div>
urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login_ldap/$', login_ldap, name='login_ldap'),
url(r'^login/$', login_view, name='login'),
url(r'^logout/$', logout_view, name='logout'),
url(r'^change_password/$', change_password, name='change_password'),
url(r'^$', index, name='index'),
]
settings.py
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
)
search_page.html
{% load static %}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link href='{% static "login.css" %}' rel="stylesheet">
<div class="wrapper">
<form method='post' action="" class="form-signin">{% csrf_token %}
<h2 class="form-signin-heading">Please login</h2>
<input type="text" class="form-control" name="username" placeholder="Username" required="" autofocus=""/>
<br>
<input type="password" class="form-control" name="password" placeholder="Password" required=""/>
<br>
<button class="btn btn-lg btn-primary btn-block" type="submit">Login</button>
</form>
</div>
回答1:
You can use get() function to get the data.
if request.method == "GET":
print ("if statement executed")
username = request.GET.get('username')
For more reference you can see here,
MultiValueDictKeyError in Django
And about POST method you may require to import the csr_exempt and use the decorator before your view.
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def myView(request):
来源:https://stackoverflow.com/questions/44727887/django-request-method-automatically-set-to-get-and-not-post