07: Django 学习补充
Posted 不做大哥好多年
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了07: Django 学习补充相关的知识,希望对你有一定的参考价值。
目录:Django其他篇
05:ModelForm 数据验证 & 生成html & 数据库操作
1.1 配置ldap认证
参考博客:https://www.cnblogs.com/dreamer-fish/p/5474289.html
官网地址:https://pypi.org/project/django-auth-ldap/1.3.0/
1、django使用ldap认证需要安装下面两个模块(这里是在linux下测试的)
1.安装Python-LDAP(python_ldap-2.4.25-cp27-none-win_amd64.whl)pip install python_ldap-2.4.25-cp27-none-win_amd64.whl
2.安装django-auth-ldap(django-auth-ldap-1.2.8.tar.gz)(下载:https://pypi.python.org/pypi/django-auth-ldap),Windows下也可以使用 python setup.py install
3. 安装成功后运行命令,运行成功表示安装成功: from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion, GroupOfNamesType
2、LDAP用户验证基本原理
1. 每个用户在LDAP系统中有一个唯一的DN值,例如配置文件中默认的admin用户在LDAP中的DN值是uid=admin,ou=system,dc=eoncloud,dc=com
,
2. 其中eoncloud.com是域名,system是组名,admin是用户名,有些LDAP用cn而不是uid来生成DN
3. 在这种系统中admin的DN看起来像这样cn=admin,ou=system,dc=eoncloud,dc=com
,无论是uid还是cn或是别的前缀,django-ldap-auth都是用dn来验证用户和获取用户信息的
4. 假设用户输入的帐号及密码是: test, password,django-auth-ldap有2个方式来获取用户的DN
1)使用AUTH_LDAP_USER_DN_TEMPLATE提供的模板生成DN.如uid=%(user)s,ou=users,dc=eoncloud,dc=com,
其中%(user)s会被替换成用户名,这样最终的DN就是 uid=test,ou=users,dc=eonclooud,dc=com.
2)使用AUTH_LDAP_GROUP_SEARCH.如果没有配置AUTH_LDAP_USER_DN_TEMPLATE,那么django-auth-ldap会使用
AUTH_LDAP_BIND_DN和AUTH_LDAP_BIND_PASSWORD提供的dn与密码根据AUTH_LDAP_GROUP_SEARCH提供的查询条件去查找test用户,
如果查不到,验证失败,如果查到用户,就使用返回的数据生成test的DN.
利用第2步生成DN值与密码尝试访问LDAP系统,如果访问成功,则验证共过,否则验证失败.
3、基本配置使用
# -*- coding:utf8 -*- import ldap from django_auth_ldap.config import LDAPSearch, PosixGroupType AUTHENTICATION_BACKENDS = ( \'django_auth_ldap.backend.LDAPBackend\', # 配置为先使用LDAP认证,如通过认证则不再使用后面的认证方式 \'django.contrib.auth.backends.ModelBackend\', # 同时打开本地认证,因为下游系统的权限和组关系需要用到 ) #默认登录后打开首页 LOGIN_REDIRECT_URL = \'/\' SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 关闭流量器不清空session SESSION_COOKIE_AGE = 60*60*8 # 8小时后session认证过期 base_dn = \'dc=cloud,dc=cn\' # 请求的域名后缀为:cloud.cn AUTH_LDAP_SERVER_URI = \'ldap://ldap-qc.intra.cloud.cn\' # LDAP系统的地址及端口号 AUTH_LDAP_BIND_DN = \'cn=cloud,ou=admin,dc=ycloud,dc=cn\' # 以admin身份查找用户及相关信息 AUTH_LDAP_BIND_PASSWORD = \'xxxxx\' # admin账号的密码 AUTH_LDAP_USER_SEARCH = LDAPSearch(\'ou=People,%s\' % base_dn, ldap.SCOPE_SUBTREE, "(uid=%(user)s)") # 第一个参数指定查询目录,第三个参数是过滤条件,过滤条件可以很复杂,有需要请查看相关文档. AUTH_LDAP_ALWAYS_UPDATE_USER = True # Default is True,是否登录后从ldap同步用户,不进行同步,因为下游的用户表是什么样的不能确定,只能确定它也使用邮箱前缀 \'\'\'一些其他配置\'\'\' # 下游系统不从ldap同步group staff/superuser相关,但需要从ldap验证用户是否离职 # AUTH_LDAP_GROUP_SEARCH = LDAPSearch(\'ou=Group,dc=ldap,dc=ssotest,dc=net\', ldap.SCOPE_SUBTREE, "(objectClass=posixGroup)") # AUTH_LDAP_GROUP_TYPE = PosixGroupType(name_attr="cn") # AUTH_LDAP_REQUIRE_GROUP = u"cn=员工,ou=Group,dc=ldap,dc=ssotest,dc=net" # AUTH_LDAP_DENY_GROUP = u"cn=黑名单,ou=Group,dc=ldap,dc=ssotest,dc=net" # AUTH_LDAP_FIND_GROUP_PERMS = True # django从ldap的组权限中获取权限,这种方式,django自身不创建组,每次请求都调用ldap,下游子系统,我们并不需要让他同步ldap里的"员工","管理员"这种表,所以不用mirror_groups # AUTH_LDAP_CACHE_GROUPS = True # 如打开FIND_GROUP_PERMS后,才生效,对组关系进行缓存,不用每次请求都调用ldap # AUTH_LDAP_GROUP_CACHE_TIMEOUT = 600 # ### ldap 配置部分END ### #
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r\'^admin/\', admin.site.urls), url(r\'^login/\', views.Login.as_view()), url(r\'^home/\', views.home, name=\'home\'),
<!DOCTYPE html> <html> <head> <meta charset=utf-8"> <title>登录</title> <link rel="stylesheet" href="/static/AdminLTE/bootstrap/css/bootstrap.css"> <link rel="stylesheet" href="/static/AdminLTE/fonts/font-awesome.min.css"> <link rel="stylesheet" href="/static/AdminLTE/ionicons/ionicons.css"> <link rel="stylesheet" href="/static/AdminLTE/dist/css/AdminLTE.css"> <style> .errorlist { color: red; } </style> </head> <body class="hold-transition login-page"> <div class="login-box"> <div class="login-logo"> <b>运维工单·平台</b> </div> <div class="login-box-body"> {% if form.errors %} <p class="errorlist">你输入的用户名密码不正确!!</p> {% endif %} <form action="" method="POST">{% csrf_token %} <div class="form-group has-feedback"> <input type="text" class="form-control" name="username" placeholder="用户名" required> <span class="glyphicon glyphicon-user form-control-feedback"></span> </div> <div class="form-group has-feedback"> <input type="password" class="form-control" name="password" placeholder="密码" required> <span class="glyphicon glyphicon-lock form-control-feedback"></span> </div> <button class="btn btn-primary btn-block btn-flat" type="submit">登陆</button> </form> <br> </div> </div> </body> </html>
1.2 在django项目中使用
# -*- coding:utf8 -*- import ldap from django_auth_ldap.config import LDAPSearch, PosixGroupType AUTHENTICATION_BACKENDS = ( \'django_auth_ldap.backend.LDAPBackend\', # 配置为先使用LDAP认证,如通过认证则不再使用后面的认证方式 \'django.contrib.auth.backends.ModelBackend\', # 同时打开本地认证,因为下游系统的权限和组关系需要用到 ) #默认登录后打开首页 LOGIN_REDIRECT_URL = \'/\' SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 关闭流量器不清空session SESSION_COOKIE_AGE = 60*60*8 # 8小时后session认证过期 base_dn = \'dc=cloud,dc=cn\' # 请求的域名后缀为:cloud.cn AUTH_LDAP_SERVER_URI = \'ldap://ldap-qc.intra.cloud.cn\' # LDAP系统的地址及端口号 AUTH_LDAP_BIND_DN = \'cn=cloud,ou=admin,dc=cloud,dc=cn\' # 以admin身份查找用户及相关信息 AUTH_LDAP_BIND_PASSWORD = \'xxxxx\' # admin账号的密码 AUTH_LDAP_USER_SEARCH = LDAPSearch(\'ou=People,%s\' % base_dn, ldap.SCOPE_SUBTREE, "(uid=%(user)s)") # 第一个参数指定查询目录,第三个参数是过滤条件,过滤条件可以很复杂,有需要请查看相关文档. AUTH_LDAP_ALWAYS_UPDATE_USER = True # Default is True,是否登录后从ldap同步用户,不进行同步,因为下游的用户表是什么样的不能确定,只能确定它也使用邮箱前缀 \'\'\'一些其他配置\'\'\' # 下游系统不从ldap同步group staff/superuser相关,但需要从ldap验证用户是否离职 # AUTH_LDAP_GROUP_SEARCH = LDAPSearch(\'ou=Group,dc=ldap,dc=ssotest,dc=net\', ldap.SCOPE_SUBTREE, "(objectClass=posixGroup)") # AUTH_LDAP_GROUP_TYPE = PosixGroupType(name_attr="cn") # AUTH_LDAP_REQUIRE_GROUP = u"cn=员工,ou=Group,dc=ldap,dc=ssotest,dc=net" # AUTH_LDAP_DENY_GROUP = u"cn=黑名单,ou=Group,dc=ldap,dc=ssotest,dc=net" # AUTH_LDAP_FIND_GROUP_PERMS = True # django从ldap的组权限中获取权限,这种方式,django自身不创建组,每次请求都调用ldap,下游子系统,我们并不需要让他同步ldap里的"员工","管理员"这种表,所以不用mirror_groups # AUTH_LDAP_CACHE_GROUPS = True # 如打开FIND_GROUP_PERMS后,才生效,对组关系进行缓存,不用每次请求都调用ldap # AUTH_LDAP_GROUP_CACHE_TIMEOUT = 600 # ### ldap 配置部分END ### #
from django.conf.urls import url from django.contrib import admin from app01 import views from django.contrib.auth.views import login, logout urlpatterns = [ url(r\'^admin/\', admin.site.urls), url(r\'^login/\', views.Login.as_view()), url(r\'^home/\', views.home, name=\'home\'), url(r\'^$\',views.index), url(r\'^ac_logout/?$\', views.logout_view, name="account_logout"), url(r\'^change_passwd/?$\', views.change_pass, name="change_passwd"), ]
# # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.shortcuts import render,HttpResponse,redirect from django.contrib.auth.views import LoginView from django.contrib.auth import login as auth_login from django.contrib.auth.decorators import login_required from django.contrib.auth import logout from django.contrib.auth.forms import PasswordChangeForm #1、登录:优先使用ldap认证,settings中配置了 class Login(LoginView): template_name = \'login.html\' def form_valid(self, form): auth_login(self.request, form.get_user()) return super(Login, self).form_valid(form) def get_context_data(self, **kwargs): context = super(Login,self).get_context_data(**kwargs) return context #2、注销 def logout_view(request): logout(request) return redirect(\'/login\') #3、修改密码:可以修改本地密码,不是修改ldap密码 @login_required(login_url=\'/login\') def change_pass(request): form = PasswordChangeForm(user=request.user) if request.method == \'POST\': form = PasswordChangeForm(request.user, request.POST) if form.is_valid(): form.save() return redirect(\'/\') return render(request, template_name=\'change_pass.html\', context={\'form\': form, \'username\': request.user.username}) #4、index首页:登陆后默认返回此页面 @login_required(login_url=\'/login\') def index(request): return render(request, \'index.html\') #5、home页面:只有登录才返回,否则返回到login页面 @login_required(login_url=\'/login\') def home(request): return HttpResponse(\'home\')
<!DOCTYPE html> <html> <head> <meta charset=utf-8"> <title>登录</title> <link rel="stylesheet" href="/static/AdminLTE/bootstrap/css/bootstrap.css"> <link rel="stylesheet" href="/static/AdminLTE/fonts/font-awesome.min.css"> <link rel="stylesheet" href="/static/AdminLTE/ionicons/ionicons.css"> <link rel="stylesheet" href="/static/AdminLTE/dist/css/AdminLTE.css"> <style> .errorlist { color: red; } </style> </head> <body class="hold-transition login-page"> <div class="login-box"> <div class="login-logo"> <b>运维工单·平台</b> </div> <div class="login-box-body"> {% if form.errors %} <p class="errorlist">你输入的用户名密码不正确!!</p> {% endif %} <form action="" method="POST">{% csrf_token %} <div class="form-group has-feedback"> <input type="text" class="form-control" name="username" placeholder="用户名" required> <span class="glyphicon glyphicon-user form-control-feedback"></span> </div> <div class="form-group has-feedback"> <input type="password" class="form-control" name="password" placeholder="密码" required> <span class="glyphicon glyphicon-lock form-control-feedback"></span> </div> <button class="btn btn-primary btn-block btn-flat" type="submit">登陆</button> </form> <br> </div> </div> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <h1>index</h1> <p><a href="{% url \'account_logout\' %}">注销</a></p> <p><a href="{% url \'home\' %}">home页面</a></p> <p><a href="{% url \'change_passwd\' %}">修改密码</a></p> <div> <h2>展示用户额外信息</h2> <p>{{ request.user }}</p> <p>{{ request.user.userprofile.zhname }}</p> </div> </body> </html>
<h1>更改密码</h1> {% block main_content %} <div class="col-md-6"> <div class="box box-info"> <div class="box-header with-border"> <h3 class="box-title">{{ request.user.username }}修改密码</h3> </div> <form class="form-horizontal" action="" method="post"> {% csrf_token %} <div class="box-body"> <div class="form-group"> <label for="id_old_password" class="col-sm-3 control-label">旧密码:</label> <div class="col-sm-9"> {{ form.old_password.errors }} {{ form.old_password }} </div> </div> <div class="form-group"> <label Python学习---django知识补充之CBV