Django + rest_framework + VUE + ldap 实现基本登陆验证

需要安装组件

  1. ldap
  2. django_auth_ldap

后端代码

setting.py 设置

  • 引入包
import json
from django.shortcuts import render_to_response,render,redirect
from django.template import RequestContext
from django.http import HttpResponse,HttpResponseRedirect
from django.contrib import auth
from rest_framework.response import Response
from rest_framework import status
from rest_framework.decorators import api_view
from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout
from django.contrib.auth.models import User
import ldap
from django_auth_ldap.config import LDAPSearch, GroupOfNamesType, PosixGroupType, LDAPGroupQuery

AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',
    'django_auth_ldap.backend.LDAPBackend',
)

AUTH_LDAP_SERVER_URI = "ldap://192.168.0.19:389"  # 服务器地址
AUTH_LDAP_BIND_DN = "DN"
AUTH_LDAP_BIND_PASSWORD = "password"

AUTH_LDAP_USER_ATTR_MAP = {  # key为数据库字段名,value为ldap中字段名,此字典解决django model与ldap字段名可能出现的不一致问题
    "username": "sAMAccountName",
    "name": "cn",
    "email": "mail",
    "first_name": "displayName"
}

base_dn='OU=XX,DC=xx,DC=com' #这个dn要根据现实场景填写
#设置用户的搜索
AUTH_LDAP_USER_SEARCH = LDAPSearch(base_dn, ldap.SCOPE_SUBTREE,
                                   "(&(objectcategory=person)(sAMAccountName=%(user)s))",
                                   attrlist=['cn', 'givenName', 'mail','sAMAccountName', 'displayName'])

AUTH_LDAP_ALWAYS_UPDATE_USER = True

在view.py中实现代码

login 我使用的

@api_view(['POST'])
def loginauth(request):
    user_loggedin = 'Guest'
    displayName = "Guest"
    errors_list = []
    context = {'username': user_loggedin, 'displayName': displayName, 'state': False}
    if request.method == 'POST':
        data = request.data
        username = data.get('username')
        password = data.get('password')
        usergo = authenticate(username=username, password=password)
        print('authuser', usergo)
        if usergo is not None:
            auth_login(request, usergo)
            uu = request.user
            user_loggedin = usergo.username
            displayName = usergo.first_name
            context = {'username': user_loggedin, 'displayName': displayName, 'state': True}
            return Response(context, status=status.HTTP_200_OK)
        return Response(context, status=status.HTTP_200_OK)

loginout

@api_view(['GET'])
def logoutauth(request):
    auth_logout(request)
    return Response(None,status=status.HTTP_200_OK)

如果是前后端分离的可以做一个接口

@api_view(['GET'])
def checklogin(request):

    user_loggedin = 'Guest'
    displayName = "Guest"
    context = {'username': user_loggedin, 'displayName': displayName, 'state': False}
    uu = request.user
    if uu:
        usergo = User.objects.filter(username=uu).first()
        if usergo is not None:
            user_loggedin = usergo.username
            displayName = usergo.first_name
            context = {'username': user_loggedin, 'displayName': displayName, 'state': True}
        return Response(context,status=status.HTTP_200_OK)
    return Response(context, status=status.HTTP_200_OK)

url.py设置

urlpatterns = [
    url(r'^login', loginauth,name="login"),
    url(r'^logout', logoutauth,name="logout"),
    url(r'^checklogin', checklogin,name="checklogin"),
    ]

前端代码

vue main.js中添加

import Vue from 'vue';
import App from './App';
import router from './router';
import axios from 'axios';
import ElementUI from 'element-ui';
import "babel-polyfill";

axios.defaults.withCredentials=true;
Vue.use(ElementUI, { size: 'mini' });
Vue.prototype.$axios = axios;
axios.defaults.baseURL ='http://0.0.0.0:8080';

//使用钩子函数对路由进行权限跳转
router.beforeEach((to, from, next) => {
    axios.get('/checklogin/').then((res) => {
        const  role =res.data.state;
        if(!role && to.path !== '/login' && to.meta.requireAuth)
        {
            next('/login');
        }else if(role && to.path == "/login")
        {
            next({path:'/index',data:role});
        }else
        {
            next();
        }

    }).catch((err) => {
        console.log(err);
    });

})

new Vue({
    router,
    render: h => h(App)
}).$mount('#app');

登陆 login.vue

<template>
    <div class="login-wrap">
        <div class="ms-title">Top Speed Data</div>
        <div class="ms-login">
            <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="0px" class="demo-ruleForm">
                <el-form-item prop="username">
                    <el-input v-model="ruleForm.username" placeholder="用户名"></el-input>
                </el-form-item>
                <el-form-item prop="password">
                    <el-input type="password" placeholder="密码" v-model="ruleForm.password" @keyup.enter.native="submitForm('ruleForm')"></el-input>
                </el-form-item>
                <div class="login-btn">
                    <el-button type="primary" @click="submitForm('ruleForm')">登录</el-button>
                </div>
                <p v-show="state" style="font-size:12px;line-height:30px;color:#ff1800;">用户名或密码错误</p>
            </el-form>
        </div>
    </div>
</template>

<script>
    export default {
        data: function(){
            return {
                ruleForm: {
                    username: '',
                    password: ''
                },
                rules: {
                    username: [
                        { required: true, message: '请输入用户名', trigger: 'blur' }
                    ],
                    password: [
                        { required: true, message: '请输入密码', trigger: 'blur' }
                    ]
                },
                state:false
            }
        },
        methods: {
            submitForm(formName) {
                var _this =this;
                _this.state = false;
                this.$refs[formName].validate((valid) => {
                    if (valid) {
                        this.$axios.post('/login/',_this.ruleForm).then((res) => {
                            if(res.data.state)
                            {
                                this.$router.push('/indwx');
                            }else
                            {
                                _this.state = true;
                            }
                        }).catch((err) => {
                            _this.state = true;
                            console.log(err);
                        });
                    } else {
                        console.log('error submit!!');
                        return false;
                    }
                });
            }
        }
    }
</script>

<style scoped>
    .login-wrap{
        position: relative;
        width:100%;
        height:100%;
    }
    .ms-title{
        position: absolute;
        top:50%;
        width:100%;
        margin-top: -230px;
        text-align: center;
        font-size:30px;
        color: #fff;

    }
    .ms-login{
        position: absolute;
        left:50%;
        top:50%;
        width:300px;
        height:160px;
        margin:-150px 0 0 -190px;
        padding:40px;
        border-radius: 5px;
        background: #fff;
    }
    .login-btn{
        text-align: center;
    }
    .login-btn button{
        width:100%;
        height:36px;
    }
</style>

退出登陆

methods:{
            // 用户名下拉菜单选择事件
            handleCommand(command) {
                if(command == 'loginout'){
                    this.$axios.get('/logoutauth/').then((res) => {
                        this.$router.push('/login');
                    }).catch((err) => {
                        console.log(err);
                    });

                }
            }
         }

猜你喜欢

转载自blog.csdn.net/weixin_39956308/article/details/80937600