VOL框架使用LDAP身份验证登录

本文介绍了作者如何在VOL框架中使用DirectoryService进行LDAP集成,以提高系统的安全性。作者分享了在部署过程中遇到的关于HTTPS和LDAPS验证的问题及解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

最近一直在VOL框架里面写管理系统,由于公司对于安全性的要求比较高,框架默认使用用户名+密码+验证码的方式,但是系统最大的威胁往往来源于内部用户,为了防止密码泄露,在框架里面自己写了个LDAP的Helper,同时为了方便部署,LDAP的所有参数都放在appsetting.json文件里。

LDAP

.net 里有多个LDAP的包,我使用了微软自己的DirectoryService,VS自带。代码找的网上的,稍微做了一些修改。代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using VOL.Core.Configuration;
using VOL.Core.Extensions;
using System.DirectoryServices;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using OfficeOpenXml.FormulaParsing.Excel.Functions.RefAndLookup;
using System.Xml.Linq;

namespace VOL.Core.Utilities.LDAP
{
    public class LDAPHelper
    {
        private DirectoryEntry _objDirectoryEntry;        
        private static string ldapUrl { get; set; }
        private static string ldapUserName { get; set; }
        private static string ldapPassword { get; set; }
        static LDAPHelper()
        {
            IConfigurationSection section = AppSetting.GetSection("LDAP");
            ldapUrl =section["ldapUrl"];
            ldapUserName = section["ldapUserName"];
            ldapPassword = section["ldapPassword"];  
        }
        public bool OpenConnection()
        {    //创建一个连接 
            _objDirectoryEntry = new DirectoryEntry(ldapUrl, ldapUserName, ldapPassword, AuthenticationTypes.ReadonlyServer);
            if (null == _objDirectoryEntry)
            {
                return false;
            }
            else if (_objDirectoryEntry.Properties != null && _objDirectoryEntry.Properties.Count > 0)
            {
                return true;
            }
            return false;
        }

        /// <summary>
                /// 检测一个用户和密码是否正确
                /// </summary>
                /// <param name="strLDAPFilter">(|(uid= {0})(cn={0}))</param>
                /// <param name="TestUserID">testuserid</param>
                /// <param name="TestUserPwd">testuserpassword</param>
                /// <param name="ErrorMessage"></param>
                /// <returns></returns>
        public bool CheckUidAndPwd(string TestUserID, string TestUserPwd, ref string ErrorMessage)
        {
            bool blRet = false;
            try
            {
                //创建一个检索
                DirectorySearcher deSearch = new DirectorySearcher(_objDirectoryEntry);
                //过滤名称是否存在
                deSearch.Filter = "sAMAccountName=" + TestUserID + "";
                deSearch.SearchScope = SearchScope.Subtree;
                //find the first instance 
                SearchResult objSearResult = deSearch.FindOne();
                //如果用户密码为空
                if (string.IsNullOrEmpty(TestUserPwd))
                {
                    if (null != objSearResult && null != objSearResult.Properties && objSearResult.Properties.Count > 0)
                    {
                        blRet = true;
                    }
                }
                else if (null != objSearResult && !string.IsNullOrEmpty(objSearResult.Path))
                {
                    //获取用户名路径对应的用户uid
                    int pos = objSearResult.Path.LastIndexOf('/');
                    string uid = objSearResult.Path.Remove(0, pos + 1);
                    DirectoryEntry objUserEntry = new DirectoryEntry(objSearResult.Path, uid, TestUserPwd, AuthenticationTypes.None);
                    if (null != objUserEntry && objUserEntry.Properties.Count > 0)
                    {
                        blRet = true;
                    }
                }
            }
            catch (Exception ex)
            {
                if (null != _objDirectoryEntry)
                {
                    _objDirectoryEntry.Close();
                }
                ErrorMessage = "检测异常:" + ex.StackTrace;
            }
            return blRet;
        }
        /// <summary>
        /// 关闭连接
        /// </summary>
        public void closeConnection()
        {
            if (null != _objDirectoryEntry)
            {
                _objDirectoryEntry.Close();
            }
        }
    }
}

appsetting.json添加LDAP配置

appsetting设置
将LDAPHelper读取的参数都放到appsetting.json文件中

VOL框架使用

1、在VOL.Core.Utilities里新建一个目录,创建LDAPHelper.cs,将上面的代码复制过去。然后找到VOL.System.Services下的System/Partial下的System_UserService.cs,添加读取设置

        string loginType = AppSetting.GetSettingString("loginType");

2、找到try块,改写登录,添加LDAP验证

try
            {
                Sys_User user = await repository.FindAsIQueryable(x => x.UserName == loginInfo.UserName)
                    .FirstOrDefaultAsync();
                if (loginType == "1")
                {
                    // 原始登录
                    if (user == null || loginInfo.Password.Trim().EncryptDES(AppSetting.Secret.User) != (user.UserPwd ?? ""))
                        return webResponse.Error(ResponseType.LoginError);                   
                }
                else
                {
                    //LDAP登录
                    LDAPHelper objldap = new LDAPHelper();
                    bool blRet = objldap.OpenConnection();
                    if (user == null || !objldap.CheckUidAndPwd(loginInfo.UserName, loginInfo.Password, ref msg))
                    {
                        return webResponse.Error(ResponseType.LoginError);
                    }
                }
                string token = JwtHelper.IssueJwt(new UserInfo()
                {
                    User_Id = user.User_Id,
                    UserName = user.UserName,
                    Role_Id = user.Role_Id
                });
                user.Token = token;
                webResponse.Data = new { token, userName = user.UserTrueName, img = user.HeadImageUrl };
                repository.Update(user, x => x.Token, true);
                UserContext.Current.LogOut(user.User_Id);

                loginInfo.Password = string.Empty;

                return webResponse.OK(ResponseType.LoginSuccess);
            }
            catch (Exception ex)
            {
                msg = ex.Message + ex.StackTrace;
                if (_context.GetService<Microsoft.AspNetCore.Hosting.IWebHostEnvironment>().IsDevelopment())
                {
                    throw new Exception(ex.Message + ex.StackTrace);
                }
                return webResponse.Error(ResponseType.ServerError);
            }
            finally
            {
                memoryCache.Remove(loginInfo.UUID);
                Logger.Info(LoggerType.Login, loginInfo.Serialize(), webResponse.Message, msg);
            }

踩坑

之前部署为http网站都没有问题,后来升级成https时候LDAP一直报异常,搞得很郁闷,上优快云提问也没有找到答案,不过给了个思路是验证LDAPS,而不是LDAP。结果把地址改为LDAPS一直不行,又找了半天,才发现验证LDAPS不需要把地址改成LDAPS,还是用LDAP,只需把端口改一下。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值