zoukankan      html  css  js  c++  java
  • 07: Django 使用ldap登录、注销等

    目录:Django其他篇

    01:Django基础篇

    02:Django进阶篇

    03:Django数据库操作--->Model

    04: Form 验证用户数据 & 生成html

    05:ModelForm 数据验证 & 生成html & 数据库操作

    06: Django Admin

    07: Django 学习补充

    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 ### #
    settings.py中配置ldap
    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'),
    app01/urls.py
    <!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>
    login.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 ### #
    settings.py中配置ldap
    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"),
    ]
    urls.py
    # # -*- 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')
    app01/views.py
    <!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>
    login.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>
    index.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 for="id_new_password1" class="col-sm-3 control-label">新密码:</label>
    
                            <div class="col-sm-9">
                                {{ form.new_password1.errors }}
                                {{ form.new_password1 }}
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="id_new_password2" class="col-sm-3 control-label">新密码确认:</label>
    
                            <div class="col-sm-9">
                                {{ form.new_password2.errors }}
                                {{ form.new_password2 }}
                            </div>
                        </div>
    
                    </div>
                    <!-- /.box-body -->
                    <div class="box-footer">
                        <button type="submit" class="btn btn-default">提交</button>
                        <button type="reset" class="btn btn-info pull-right">重置</button>
                    </div>
                    <!-- /.box-footer -->
                </form>
            </div>
        </div>
    {% endblock %}
    change_pass.html
    # -*- coding: utf-8 -*-
    from __future__ import unicode_literals
    
    from django.db import models
    from django.contrib.auth.models import User
    
    class UserProfile(models.Model):
        user = models.OneToOneField(User,verbose_name='用户名')
        zhname = models.CharField(max_length=50,verbose_name='姓名',blank=True,null=True)
    app01/models.py 中使用UserProfile表为User表添加额外信息

       1、页面效果

         

      2、说明

          1. 我们只需要在settings中配置使用ldap认证后,django就可以利用ldap进行认证了

          2、然后我们利用django内置模块 LoginView 定义登录界面视图函数 Login(LoginView) 来验证ldap身份

          3、需要身份认证的视图函数仅需使用django的 login_required 模块进行装饰即可:@login_required(login_url='/login')

  • 相关阅读:
    可重入锁 RLOCK(转)
    python 全局变量的简单理解
    urlopen设置代理方法
    python is id == 的差别,cmp方法
    FutureTask
    Java基础复习
    计算机编程底层基础
    Microsoft.NET框架程序设计20 CLR寄宿、应用程序域、反射
    Microsoft.NET框架程序设计19 自动内存管理(垃圾收集)
    Microsoft.NET框架程序设计17 委托
  • 原文地址:https://www.cnblogs.com/xiaonq/p/8012889.html
Copyright © 2011-2022 走看看