Django request.method automatically set to GET and not POST

本秂侑毒 提交于 2019-12-24 19:13:54

问题


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

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