近期在练手Django,前期网站前后端已经搭建得差不多了。
后面打算加入LDAP进行后台数据库登录授权,使用的Django的admin界面。
Django的admin界面还是很开发友好的,省区了很多数据库展示开发的工作,可以搜索“Django二次开发”发现更多的内容。
LDAP知识
LDAP是一个协议,而开源的LDAP和微软的Active Directory都是支持这个协议的。
一般我们Windows会使用AD做域控,LDAP的一些基础概念可以看下如下文章:
LDAP 中 CN, OU, DC 的含义_ba_jie的博客-CSDN博客_ldap ou
了解了这些可以帮助我们配置各大服务的LDAP部分。
一、安装LDAP相关库
虽然很快就能搜到Django LDAP方案代码,但是我发现我为了装ldap相关库,竟然踩了些坑。总结一下,给有需要的同学。
方案:django中ldap验证的三种方式,你需要哪种?_Tian, Yuting的博客-CSDN博客_django ldap
准备参考这篇文章的时候,发现我的django_auth_ldap没有装,需要安装django-auth-ldap,使用pycharm安装时,由于是源码安装,总是报C++的问题。
解决方法:使用whl安装。
下载whl:
Python Extension Packages for Windows - Christoph Gohlke (uci.edu)
1. 先安装pyldap或python_ldap, 我安装的版本是python_ldap-3.4.0-cp37-cp37m-win_amd64.whl,将whl下载并放到Scripts目录下,cd **/Scripts后用pip安装:
C:\Users\XXX\PycharmProjects\djangoProject\venv\Scripts> pip install python_ldap-3.4.0-cp37-cp37m-win_amd64.whl
Processing c:\users\XXX\pycharmprojects\djangoproject\venv\scripts\python_ldap-3.4.0-cp37-cp37m-win_amd64.whl
Requirement already satisfied: pyasn1>=0.3.7 in c:\users\XXX\pycharmprojects\djangoproject\venv\lib\site-packages (from python-ldap==3.4.0) (0.4.8)
Collecting pyasn1-modules>=0.1.5
Using cached pyasn1_modules-0.2.8-py2.py3-none-any.whl (155 kB)
Installing collected packages: pyasn1-modules, python-ldap
Successfully installed pyasn1-modules-0.2.8 python-ldap-3.4.0
2. 安装:django-ahth-ldap
C:\Users\XXX\PycharmProjects\djangoProject\venv\Scripts> pip install django_auth_ldap-4.1.0-py30-none-any.whl
该安装包地址:https://www.wheelodex.org/projects/django-auth-ldap/wheels/django_auth_ldap-4.1.0-py3-none-any.whl/
注意我们下载下来的名称要改成本地python兼容tag名称:
输入:pip debug --verbose 查看兼容名称
参考文章:python 安装whl文件_ Marks的博客-CSDN博客_python手动安装whl
C:\Program Files\Python37\Scripts>pip debug --verbose
WARNING: This command is only meant for debugging. Do not use this with automation for parsing and getting these details, since the output and options of this command may change without notice.
pip version: pip 20.1.1 from c:\program files\python37\lib\site-packages\pip (python 3.7)
sys.version: 3.7.9 (tags/v3.7.9:13c94747c7, Aug 17 2020, 18:58:18) [MSC v.1900 64 bit (AMD64)]
sys.executable: c:\program files\python37\python.exe
sys.getdefaultencoding: utf-8
sys.getfilesystemencoding: utf-8
locale.getpreferredencoding: cp936
sys.platform: win32
sys.implementation:
name: cpython
'cert' config value: Not specified
REQUESTS_CA_BUNDLE: None
CURL_CA_BUNDLE: None
pip._vendor.certifi.where(): c:\program files\python37\lib\site-packages\pip\_vendor\certifi\cacert.pem
pip._vendor.DEBUNDLED: False
vendored library versions:
appdirs==1.4.3
CacheControl==0.12.6
colorama==0.4.3
contextlib2==0.6.0.post1 (Unable to locate actual module version, using vendor.txt specified version)
distlib==0.3.0
distro==1.5.0 (Unable to locate actual module version, using vendor.txt specified version)
html5lib==1.0.1
ipaddress==1.0.23
msgpack==1.0.0 (Unable to locate actual module version, using vendor.txt specified version)
packaging==20.3
pep517==0.8.2
progress==1.5
pyparsing==2.4.7
requests==2.23.0
certifi==2020.04.05.1
chardet==3.0.4
idna==2.9
urllib3==1.25.8
resolvelib==0.3.0
retrying==1.3.3 (Unable to locate actual module version, using vendor.txt specified version)
setuptools==44.0.0 (Unable to locate actual module version, using vendor.txt specified version)
six==1.14.0
toml==0.10.0
webencodings==0.5.1 (Unable to locate actual module version, using vendor.txt specified version)
Compatible tags: 27
cp37-cp37m-win_amd64
cp37-abi3-win_amd64
cp37-none-win_amd64
cp36-abi3-win_amd64
cp35-abi3-win_amd64
cp34-abi3-win_amd64
cp33-abi3-win_amd64
cp32-abi3-win_amd64
py37-none-win_amd64
py3-none-win_amd64
py36-none-win_amd64
py35-none-win_amd64
py34-none-win_amd64
py33-none-win_amd64
py32-none-win_amd64
py31-none-win_amd64
py30-none-win_amd64
cp37-none-any
py37-none-any
py3-none-any
py36-none-any
py35-none-any
py34-none-any
py33-none-any
py32-none-any
py31-none-any
py30-none-any
这样django-auth-ldap就安装好啦。
Linux上安装很简单:
- 安装依赖库:
sudo yum install python-devel
sudo yum install openldap-devel
安装django-auth-ldap
pip install django-auth-ldap
二、LDAP授权功能调试
修改settings.py文件:
笔者参考的这篇文档:Django-auth-ldap 配置方法 - 云+社区 - 腾讯云
注意要加入一个超级用户的用户名和密码,参考文档:Authentication — django-auth-ldap 4.0.1.dev12+g6dfdec9.d20220510 documentation
AUTH_LDAP_BIND_DN = ""
AUTH_LDAP_BIND_PASSWORD = ""
以下是我测试可用的代码:
#Django-auth-ldap 配置部分
import ldap
from django_auth_ldap.config import LDAPSearch, GroupOfNamesType
#修改Django认证先走ldap,再走本地认证
AUTHENTICATION_BACKENDS = [
'django_auth_ldap.backend.LDAPBackend',
'django.contrib.auth.backends.ModelBackend',
]
#ldap的连接基础配置
AUTH_LDAP_SERVER_URI = "ldap://****:389"
AUTH_LDAP_BIND_DN = "***"
AUTH_LDAP_BIND_PASSWORD = "*****"
AUTH_LDAP_USER_SEARCH = LDAPSearch("OU=group1,DC=company,DC=com",
ldap.SCOPE_SUBTREE, "(sAMAccountName=%(user)s)")
#通过组进行权限控制
AUTH_LDAP_GROUP_SEARCH = LDAPSearch("OU=group2,OU=group1,DC=company,DC=com",
ldap.SCOPE_SUBTREE, "(objectClass=groupOfNames)")
AUTH_LDAP_GROUP_TYPE = GroupOfNamesType()
#is_staff:这个组里的成员可以登录;is_superuser:组成员是django admin的超级管理员;is_active:组成员可以登录django admin后台,但是无权限查看后台内容
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
"is_staff": "CN=group_account,OU=group2,OU=group1,DC=company,DC=com",
"is_superuser": "CN=group_account,OU=group2,OU=group1,DC=company,DC=com",
}#通过组进行权限控制end
#如果ldap服务器是Windows的AD,需要配置上如下选项
AUTH_LDAP_CONNECTION_OPTIONS = {
ldap.OPT_DEBUG_LEVEL: 1,
ldap.OPT_REFERRALS: 0,
}
#当ldap用户登录时,从ldap的用户属性对应写到django的user数据库,键为django的属性,值为ldap用户的属性
AUTH_LDAP_USER_ATTR_MAP = {
"first_name": "givenName",
"last_name": "sn",
"email": "mail"}
完成以上修改后,http://localhost/admin 界面就可以通过LDAP授权登录了。
凡是在LDAP群组里的用户均可登录该界面。但是我想要的是前端自己开发的界面也通过LDAP授权。
三、登录界面开发
Django开发有很多隐藏功能,但是好处是资料很多,在网上搜集了一番后,得出自己的前端开发程序。
首先,找一个好看的html页面,我用的是AdminLTE-2.3.0的模板。
html页面中的form如下:
<body class="hold-transition login-page">
<div class="login-box">
<div class="login-logo">
<a href="../../index.html">Name</a>
</div><!-- /.login-logo -->
<div class="login-box-body">
<p class="login-box-msg">Sign in to start your session</p>
<form action="/login" method="post">
{% if message %}
<div class="alert alert-warning">{{ message }}</div>
{% endif %}
{% csrf_token %}
<div class="form-group has-feedback">
<input type="text" name="username" class="form-control" placeholder="username">
<span class="glyphicon glyphicon-envelope form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
<input type="password" name="password" class="form-control" placeholder="password">
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<div class="row">
<div class="col-xs-8">
<div class="checkbox icheck">
<label>
<input type="checkbox"> Remember Me
</label>
</div>
</div><!-- /.col -->
<div style="display: none;">
<input id="next" type="text" name="next_url" value="{{ next_url }}" />
</div>
<div class="col-xs-4">
<button type="submit" class="btn btn-primary btn-block btn-flat">Sign In</button>
</div><!-- /.col -->
</div>
</form>
<a href="change_password">change password</a><br>
<a href="register" class="text-center">Register a new membership</a>
</div><!-- /.login-box-body -->
</div><!-- /.login-box -->
配合的还需要修改 app中的urls.py和views.py
urls.py:
urlpatterns = [
path('', views.index, name='index'),
path('index.html', views.index, name='index'),
path('login', views.login_view, name='login'),
]
views.py
def login_view(request):
"""entry function of login page"""
if request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
next_url = request.POST.get("next_url")
message = '请检查填写的内容!'
if username.strip() and password:
if authenticate(username=username, password=password):
user = authenticate(username=username, password=password)
if next_url and next_url != "logout":
response = redirect(next_url)
login(request, user)
else:
# response = redirect("index.html")
login(request, user)
response = redirect("index.html")
# return redirect('index.html')
return response
else:
message = '用户名或密码不正确!'
return render(request, 'dashboard/pages/login/login.html', {'message': message})
else:
return render(request, 'dashboard/pages/login/login.html', {'message': message})
next_url = request.GET.get("next", '')
return render(request, 'dashboard/pages/login/login.html', {'next_url': next_url})
这样通过authenticate(username=username, password=password),我们自己的登录界面走的就是LDAP验证了。



2347

被折叠的 条评论
为什么被折叠?



