GVKun编程网logo

go LDAP 连接池实现 【LDAP Result Code 200 \"Network Error\": ldap: connection is in startls phase】

9

本文的目的是介绍goLDAP连接池实现【LDAPResultCode200\"NetworkError\":ldap:connectionisinstartlsphase】的详细情况,我们将通过专业的

本文的目的是介绍go LDAP 连接池实现 【LDAP Result Code 200 \"Network Error\": ldap: connection is in startls phase】的详细情况,我们将通过专业的研究、有关数据的分析等多种方式,同时也不会遗漏关于Android Studio 3.1.4 buildApk遇到问题 Connection reset、asp.net-core – 来自带有Entity Framework Core的Data Tier中的appsettings.json的ConnectionString、c# – Net Core Connection String Dapper visual studio 2017、Client network socket disconnected before secure TLS connection was established的知识。

本文目录一览:

go LDAP 连接池实现 【LDAP Result Code 200 \

go LDAP 连接池实现 【LDAP Result Code 200 \"Network Error\": ldap: connection is in startls phase】

LDAP 连接池

简介

场景:写了个定时任务,每天下午 5 点根据 HR 数据对全量 LDAP 用户作更新,因为 LDAP 协议是一种可以快速读但修改操作慢的协议,因此定时任务执行时间会很长。于是决定并发地对全量用户进行更新,假设并发数是 20,那么一次性会开始创建 20 个 LDAP 连接,因为 LDAP 连接速度较慢,会报错 LDAP Result Code 200 \"Network Error\": ldap: connection is in startls phase

通过思考和调研,决定仿照 MySQL、Redis 连接池那样在主进程启动后先初始化 LDAP 连接池。找到并改写 5 年前一个国外的老仓库,并测试通过,完美地解决了问题。现将源码和使用方式给出,后面也会作优化~

源码: randolphcyg/ldappool

使用方式

// 拉下包
go get "github.com/randolphcyg/ldappool"
// 导入
import ldappool "github.com/randolphcyg/ldappool"

示例

在自己的项目中写一个 Init 函数,主进程中解析出来 ldap 服务器连接信息后初始化 ldap 连接池,得到一个全局的连接池对象 LdapPool ,用到的地方用 LdapPool.Get() 获取连接即可。后续开发若有并发修改 ldap 信息的需求,即可快速从连接池取连接,作并发操作。


package main

import (
	"crypto/tls"
	"fmt"
	"time"
	"unicode/utf16"

	"github.com/randolphcyg/ldappool"
	"github.com/go-ldap/ldap/v3"
	"github.com/sirupsen/logrus"
	"gorm.io/gorm"
)

func main() {
	c := &ldapCfg{
		ConnUrl:       "ldap://192.168.xx.xx:389",
		SslEncryption: true,
		Timeout:       5 * time.Second,
		BaseDn:        "DC=xxx,DC=com",
		AdminAccount:  "CN=Admin,CN=Users,DC=xxx,DC=com",
		Password:      "xxx",
	}
	// 初始化配置ldap连接池
	Init(c)

	// 待查询用户
	ldapUser := &LdapAttributes{
		Num:         "工号",
		DisplayName: "姓名",
	}

	entry, err := FetchUser(ldapUser)
	if err != nil {
		logrus.Error("fail to fetch ldap user", err)
	}
	fmt.Println(entry.DN)
}

// LdapConnCfg LDAP服务器连接配置
type ldapCfg struct {
	gorm.Model
	// 连接地址
	ConnUrl string `json:"conn_url" gorm:"type:varchar(255);unique_index;not null;comment:连接地址 逻辑外键"`
	// SSL加密方式
	SslEncryption bool `json:"ssl_encryption" gorm:"type:tinyint;length:1;comment:SSL加密方式"`
	// 超时设置
	Timeout time.Duration `json:"timeout" gorm:"type:int;comment:超时设置"`
	// 根目录
	BaseDn string `json:"base_dn" gorm:"type:varchar(255);not null;comment:根目录"`
	// 用户名
	AdminAccount string `json:"admin_account" gorm:"type:varchar(255);not null;comment:用户名"`
	// 密码
	Password string `json:"password" gorm:"type:varchar(255);not null;comment:密码"`
}

var LdapCfg *ldapCfg
var LdapPool ldappool.Pool

// Init 初始化连接池
func Init(c *ldapCfg) (err error) {
	LdapCfg = &ldapCfg{
		ConnUrl:       c.ConnUrl,
		SslEncryption: c.SslEncryption,
		Timeout:       c.Timeout,
		BaseDn:        c.BaseDn,
		AdminAccount:  c.AdminAccount,
		Password:      c.Password,
	}
	// 初始化ldap连接池 TODO 待确认参数
	n := utf16.Encode([]rune("3"))
	LdapPool, err = ldappool.NewChannelPool(50, 1000, "test",
		func(s string) (ldap.Client, error) {
			conn, err := ldap.DialURL(LdapCfg.ConnUrl)
			if err != nil {
				logrus.Error("Fail to dial ldap url, err: ", err)
			}

			// 重新连接TLS
			if err = conn.StartTLS(&tls.Config{InsecureSkipVerify: true}); err != nil {
				logrus.Error("Fail to start tls, err: ", err)
			}

			// 与只读用户绑定
			if err = conn.Bind(LdapCfg.AdminAccount, LdapCfg.Password); err != nil {
				logrus.Error("admin user auth failed, err: ", err)
			}
			return conn, nil
		}, n)
	if err != nil {
		logrus.Error(err.Error())
	}
	return
}

type LdapAttributes struct {
	// ldap字段
	Num         string `json:"employeeNumber" gorm:"type:varchar(100);unique_index"`    // 工号
	Sam         string `json:"sAMAccountName" gorm:"type:varchar(128);unique_index"`    // SAM账号
	Dn          string `json:"distinguishedName" gorm:"type:varchar(100);unique_index"` // dn
	AccountCtl  string `json:"UserAccountControl" gorm:"type:varchar(100)"`             // 用户账户控制
	Expire      int64  `json:"accountExpires" gorm:"type:int(30)"`                      // 账户过期时间
	PwdLastSet  string `json:"pwdLastSet" gorm:"type:varchar(100)"`                     // 用户下次登录必须修改密码
	WhenCreated string `json:"whenCreated" gorm:"type:varchar(100)"`                    // 创建时间
	WhenChanged string `json:"whenChanged" gorm:"type:varchar(100)"`                    // 修改时间
	DisplayName string `json:"displayName" gorm:"type:varchar(32)"`                     // 真实姓名
	Sn          string `json:"sn" gorm:"type:varchar(100)"`                             // 姓
	Name        string `json:"name" gorm:"type:varchar(100)"`                           // 姓名
	GivenName   string `json:"givenName" gorm:"type:varchar(100)"`                      // 名
	Email       string `json:"mail" gorm:"type:varchar(128);unique_index"`              // 邮箱
	Phone       string `json:"mobile" gorm:"type:varchar(32);unique_index"`             // 移动电话
	Company     string `json:"company" gorm:"type:varchar(128)"`                        // 公司
	Depart      string `json:"department" gorm:"type:varchar(128)"`                     // 部门
	Title       string `json:"title" gorm:"type:varchar(100)"`                          // 职务
}

var attrs = []string{
	"employeeNumber",     // 工号
	"sAMAccountName",     // SAM账号
	"distinguishedName",  // dn
	"UserAccountControl", // 用户账户控制
	"accountExpires",     // 账户过期时间
	"pwdLastSet",         // 用户下次登录必须修改密码
	"whenCreated",        // 创建时间
	"whenChanged",        // 修改时间
	"displayName",        // 显示名
	"sn",                 // 姓
	"name",
	"givenName",  // 名
	"mail",       // 邮箱
	"mobile",     // 手机号
	"company",    // 公司
	"department", // 部门
	"title",      // 职务
	"cn",         // common name
}

/* 根据cn查询用户 注意: cn查询不到则会返回管理员用户
 * 这里的查询条件必须保证每个用户必须有
 * 根据cn查询用户 [sam登录名字段也出现了不同的版本 邮箱\手机号都可能更换掉 真实姓名存在重复可能]
 */
func FetchUser(user *LdapAttributes) (result *ldap.Entry, err error) {
	// 获取连接
	LdapConn, err := LdapPool.Get()
	if err != nil {
		logrus.Error("Fail to get ldap connection, err: ", err)
		return
	}
	defer LdapConn.Close()

	ldapFilterCn := "(cn=" + user.DisplayName + user.Num + ")"
	searchFilter := "(objectClass=organizationalPerson)"

	if user.DisplayName != "" && user.Num != "" {
		searchFilter += ldapFilterCn
	}
	searchFilter = "(&" + searchFilter + ")"

	searchRequest := ldap.NewSearchRequest(
		LdapCfg.BaseDn,
		ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
		searchFilter,
		attrs,
		nil,
	)

	// 这里LdapConn 为nil
	sr, err := LdapConn.Search(searchRequest)
	if err != nil {
		logrus.Error("Fail to fetch user, err: ", err)
		return
	}
	if len(sr.Entries) > 0 && len(sr.Entries[0].Attributes) > 0 {
		result = sr.Entries[0]
	}
	return
}

问题

15 分钟后创建的 50 个 ldap 连接会被关闭,如何解决这个问题呢?

NewChannelPoolaliveChecks 改为 true 即可。这个是允许存活校验。

failed to send closeNotify alert (but connection was closed anyway): write tcp x.x.x.x:13739->x.x.x.x:389: wsasend: An existing connection was forcibly closed by the remote host.

Android Studio 3.1.4 buildApk遇到问题 Connection reset

Android Studio 3.1.4 buildApk遇到问题 Connection reset

打开设置,找到Android Studio选项卡,把下图选项打上勾就ok

asp.net-core – 来自带有Entity Framework Core的Data Tier中的appsettings.json的ConnectionString

asp.net-core – 来自带有Entity Framework Core的Data Tier中的appsettings.json的ConnectionString

我有一个新的应用程序,我正在使用Entity Framework Core构建ASP.NET Core.该应用程序具有UI,模型,业务和数据层.在以前的ASP.NET版本中,您可以在web.config中设置连接字符串,默认情况下它将在引用的层中可用.在使用appsettings.json(或其他配置选项)的ASP.NET Core中,这似乎不是相同的情况?有关如何实现这一点的任何想法?我在数据层中配置了dbcontext,但我目前正在对连接字符串进行硬编码.

我看到的所有示例都在startup.cs的UI层中配置了dbcontext.这就是我想要避免的.

问题Here得到了主题.

解决方法

您可以轻松地将IServiceCollection的扩展方法添加到业务/服务层,并使用它来注册自己的依赖项.然后在启动时,您只需在服务层上调用该方法,而无需在Web应用程序中引用EntityFramework.

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace your.service.layer
{
    public static class MyServiceCollectionExtensions
    {
        public static IServiceCollection AddMyServiceDependencies(this IServiceCollection services,string connectionString)
        {
             services.AddEntityFrameworksqlServer()
            .AddDbContext<YourDbContext>((serviceProvider,options) =>
            options.UsesqlServer(connectionString)
                   .UseInternalServiceProvider(serviceProvider)
                   );
             return services;
        }
    }

}

启动:

using your.service.layer;

public void ConfigureServices(IServiceCollection services)
{
    var connectionString = Configuration.GetConnectionString("EntityFrameworkConnectionString");
    services.AddMyServiceDependencies(connectionString);
}

现在,您的网络应用仅需要对您的业务/服务层的引用,并且它不直接依赖于EntityFramework.

c# – Net Core Connection String Dapper visual studio 2017

c# – Net Core Connection String Dapper visual studio 2017

我试图在我的.Net Core应用程序中设置连接字符串,但我一直收到错误:

System.NullReferenceException:’对象引用未设置为对象的实例.’

我尝试将以下内容添加到appsettings.json:

"ConnectionStrings": {

"Analysis": "Server=DESKTOP-MYSERVER;Database=MYDATABASE;User Id=sa; Password=Password123;Provider=System.Data.sqlClient;Trusted_Connection=True;MultipleActiveResultSets=true;Pooling=false;"
}

我也试过像以前那样使用web.config .Net Core:

<connectionStrings>
<add name="Analysis" providerName="System.Data.sqlClient" 
     connectionString="Server=DESKTOP-MYSERVER;Database=MYDATABASE;User Id=sm;Password=Password123;"/>

然后在c#我有:

public List<DapperTest> ReadAll()
    {
        var data = new List<DapperTest>();
        using (IDbConnection db = new sqlConnection(ConfigurationManager.ConnectionStrings["Analysis"].ConnectionString))
        {
             data = db.Query<DapperTest>("select * from testTable").ToList();
        }

        return data;
    }

两种方式都给我例外:

System.NullReferenceException:’对象引用未设置为对象的实例.’

我使用了以下资源:

.Net CORE Dapper Connection String?

https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro

Get connection string from App.config

但我错过了一些东西.我只设置了一次连接字符串,它不在.Net Core中,因此对其他人来说显而易见.

解决方法

如果您正在使用appsettings.json,请创建一个简单的POCO类来为您的连接字符串配置建模,如下所示:
public class ConnectionConfig
{
        public string Analysis {get;set;}
}

在Startup.cs中的ConfigureServices方法中添加此行

services.Configure<ConnectionConfig>(Configuration.GetSection("ConnectionStrings"));

数据服务类

class YourClass{
    private string _connectionString;

    YourClass(string connectionString){
       _connectionString = connectionString;
    }

    //Your implementation
    public List<DapperTest> ReadAll()
    {
        var data = new List<DapperTest>();
        using (IDbConnection db = new sqlConnection(_connectionString)
        {
            data = db.Query<DapperTest>("select * from testTable").ToList();
        }

       return data;
   }
}

注入IOptions< ConnectionConfig>在你的控制器构造函数中.

class YourController : Controller{
   YourClass _testing;

   YourController(IOptions<ConnectionConfig> connectionConfig){
       var connection = connectionConfig.Value;
       string connectionString = connection.Analysis;
       _testing = new YourClass(connectionString );
    }
   public IActionResult Index() { 
        var testingData = _testing.ReadAll(); 
        return View(); 
     }
 }

Client network socket disconnected before secure TLS connection was established

Client network socket disconnected before secure TLS connection was established

标题:Client network socket disconnected before secure TLS connection was established

我在使用 SAP Spartacus 连接 Commerce Cloud 后台 OCC API 时,遇到如下错误消息:

Error: Client network socket disconnected before secure TLS connection was established
at connResetException (internal/errors.js:610:14)
at TLSSocket.onConnectEnd (_tls_wrap.js:1546:19)
at Object.onceWrapper (events.js:421:28)
at ZoneDelegate.invokeTask (c:\Code\SPA\strange\mystore\dist\mystore\server\main.js:140414:35)
at Object.onInvokeTask (c:\Code\SPA\strange\mystore\dist\mystore\server\main.js:174114:33)
at ZoneDelegate.invokeTask (c:\Code\SPA\strange\mystore\dist\mystore\server\main.js:140413:40)
at Zone.runTask (c:\Code\SPA\strange\mystore\dist\mystore\server\main.js:140181:51)
at ZoneTask.invokeTask (c:\Code\SPA\strange\mystore\dist\mystore\server\main.js:140496:38)
at TLSSocket.ZoneTask.invoke (c:\Code\SPA\strange\mystore\dist\mystore\server\main.js:140485:52)
at TLSSocket.emit (events.js:327:22)

调试截图:

解决方案

将所有的 OCC 调用经过一个本地 reverse-proxy 进行路由 (基于 npm http-proxy-cli)。

(1) set “CX_BASE_URL”: “http://localhost:4500” in .env-cmdrc file (:4500, 端口可以任意指定)

(2) rebuild app and ssr, and serve ssr
Proxy calls to our OCC dev server (https://40……) through http://localhost:4500 , and ignore TLS issues (–no-verify), and optionally make it verbose (-v)

使用下面的命名行安装 http-proxy-cli

$ npm install -g http-proxy-cli

run

$ http-proxy -p 4500 -P --no-verify -v https://40.x.x.x:9002

更多 Jerry 的原创文章,尽在:“汪子熙”:

本文同步分享在 博客 “汪子熙”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与 “OSC 源创计划”,欢迎正在阅读的你也加入,一起分享。

我们今天的关于go LDAP 连接池实现 【LDAP Result Code 200 \"Network Error\": ldap: connection is in startls phase】的分享就到这里,谢谢您的阅读,如果想了解更多关于Android Studio 3.1.4 buildApk遇到问题 Connection reset、asp.net-core – 来自带有Entity Framework Core的Data Tier中的appsettings.json的ConnectionString、c# – Net Core Connection String Dapper visual studio 2017、Client network socket disconnected before secure TLS connection was established的相关信息,可以在本站进行搜索。

本文标签: