소스 검색

DOP接口平台提交

Murphy 2 년 전
부모
커밋
06e1c1654d
21개의 변경된 파일1319개의 추가작업 그리고 0개의 파일을 삭제
  1. 51 0
      MicroServices/DopInterfacePlatform/ClientIpCheckActionFilter.cs
  2. 40 0
      MicroServices/DopInterfacePlatform/Controllers/TokenController.cs
  3. 73 0
      MicroServices/DopInterfacePlatform/Controllers/WeatherForecastController.cs
  4. 23 0
      MicroServices/DopInterfacePlatform/DopInterfacePlatform.csproj
  5. 7 0
      MicroServices/DopInterfacePlatform/DopInterfacePlatform.csproj.user
  6. 25 0
      MicroServices/DopInterfacePlatform/DopInterfacePlatform.sln
  7. 14 0
      MicroServices/DopInterfacePlatform/DopInterfacePlatformContext.cs
  8. 49 0
      MicroServices/DopInterfacePlatform/Entity/InterfacePlatformLog.cs
  9. 9 0
      MicroServices/DopInterfacePlatform/Interface/IJwtService.cs
  10. 55 0
      MicroServices/DopInterfacePlatform/IpWhiteListMiddleware.cs
  11. 28 0
      MicroServices/DopInterfacePlatform/JWTExtensions.cs
  12. 25 0
      MicroServices/DopInterfacePlatform/JwtOptions.cs
  13. 108 0
      MicroServices/DopInterfacePlatform/LogFilter.cs
  14. 66 0
      MicroServices/DopInterfacePlatform/Program.cs
  15. 31 0
      MicroServices/DopInterfacePlatform/Properties/launchSettings.json
  16. 21 0
      MicroServices/DopInterfacePlatform/Service/JwtService.cs
  17. 610 0
      MicroServices/DopInterfacePlatform/StringHelper.cs
  18. 44 0
      MicroServices/DopInterfacePlatform/SwaggerGenOptionsExtensions.cs
  19. 13 0
      MicroServices/DopInterfacePlatform/WeatherForecast.cs
  20. 8 0
      MicroServices/DopInterfacePlatform/appsettings.Development.json
  21. 19 0
      MicroServices/DopInterfacePlatform/appsettings.json

+ 51 - 0
MicroServices/DopInterfacePlatform/ClientIpCheckActionFilter.cs

@@ -0,0 +1,51 @@
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+using System.Net;
+
+namespace WebApiTest
+{
+    public class ClientIpCheckActionFilter : ActionFilterAttribute
+    {
+        private readonly ILogger _logger;
+        private readonly string _safelist;
+
+        public ClientIpCheckActionFilter(string safelist, ILogger logger)
+        {
+            _safelist = safelist;
+            _logger = logger;
+        }
+
+        public override void OnActionExecuting(ActionExecutingContext context)
+        {
+            var remoteIp = context.HttpContext.Connection.RemoteIpAddress;
+            _logger.LogDebug("Remote IpAddress: {RemoteIp}", remoteIp);
+            var ip = _safelist.Split(';');
+            var badIp = true;
+
+            if (remoteIp.IsIPv4MappedToIPv6)
+            {
+                remoteIp = remoteIp.MapToIPv4();
+            }
+
+            foreach (var address in ip)
+            {
+                var testIp = IPAddress.Parse(address);
+
+                if (testIp.Equals(remoteIp))
+                {
+                    badIp = false;
+                    break;
+                }
+            }
+
+            if (badIp)
+            {
+                _logger.LogWarning("Forbidden Request from IP: {RemoteIp}", remoteIp);
+                context.Result = new StatusCodeResult(StatusCodes.Status403Forbidden);
+                return;
+            }
+
+            base.OnActionExecuting(context);
+        }
+    }
+}

+ 40 - 0
MicroServices/DopInterfacePlatform/Controllers/TokenController.cs

@@ -0,0 +1,40 @@
+using DopInterfacePlatform.Interface;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Options;
+using System.Security.Claims;
+
+namespace DopInterfacePlatform.Controllers
+{
+    [Route("api/[controller]")]
+    [ApiController]
+    public class TokenController : ControllerBase
+    {
+        public IJwtService _jwtService { set; get; }
+
+        private IConfiguration _configuration;
+        public TokenController(IJwtService jwtService, IConfiguration configuration)
+        {
+            _jwtService = jwtService;
+            _configuration = configuration;
+        }
+
+        [AllowAnonymous]
+        [HttpGet]
+        [Route("token")]
+        public string GetToken()
+        {
+            JwtOptions jwtOptions=new JwtOptions();
+            jwtOptions.ExpireSeconds = Convert.ToInt32(_configuration["JWT:ExpireSeconds"]);
+            jwtOptions.Issuer = _configuration["JWT:Issuer"];
+            jwtOptions.Audience = _configuration["JWT:Audience"];
+            jwtOptions.Key = _configuration["JWT:Key"];
+            List<Claim> claims = new List<Claim>();
+            claims.Add(new Claim(ClaimTypes.Name, "用户1"));
+            claims.Add(new Claim(ClaimTypes.Role, "超级管理员"));
+            return _jwtService.BuildToken(claims, jwtOptions);
+        }
+    }
+}

+ 73 - 0
MicroServices/DopInterfacePlatform/Controllers/WeatherForecastController.cs

@@ -0,0 +1,73 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using System.ServiceModel;
+using System.Xml;
+
+namespace DopInterfacePlatform.Controllers
+{
+    [ApiController]
+    [Route("[controller]/[action]")]
+    [Authorize]
+    public class WeatherForecastController : ControllerBase
+    {
+        private static readonly string[] Summaries = new[]
+        {
+        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
+    };
+
+        private readonly ILogger<WeatherForecastController> _logger;
+
+        public WeatherForecastController(ILogger<WeatherForecastController> logger)
+        {
+            _logger = logger;
+        }
+
+        [HttpGet(Name = "GetWeatherForecast")]
+        [Authorize]
+        public IEnumerable<WeatherForecast> Get()
+        {
+            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
+            {
+                Date = DateTime.Now.AddDays(index),
+                TemperatureC = Random.Shared.Next(-20, 55),
+                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
+            })
+            .ToArray();
+        }
+
+        [HttpGet(Name = "GetByCount")]
+        [Authorize]
+        public int GetByCount(int count)
+        {
+            return count+7;
+        }
+
+
+        [HttpGet(Name = "GetByCount1")]
+        [Authorize]
+        public int GetByCount1(int count,int count2)
+        {
+            return count + 7+count2;
+        }
+
+        [HttpGet(Name = "TestWebservice")]
+        [Authorize]
+        public string TestWebservice()
+        {
+            var parameters = new Dictionary<string, string> { { "byProvinceName", "湖北" } };
+            HttpContent httpContent = new FormUrlEncodedContent(parameters);
+
+            // contentType对应 webservice提示 如下图
+            httpContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
+            HttpClient httpClient = new HttpClient();
+            HttpResponseMessage response = httpClient.PostAsync("http://www.webxml.com.cn/WebServices/WeatherWebService.asmx/getSupportCity", httpContent).Result;
+            var statusCode = response.StatusCode.ToString();
+            var result = response.Content.ReadAsStringAsync().Result;
+            var doc = new XmlDocument();
+            doc.LoadXml(result);
+            // xml返回值数据所在标签,替换成你的xml结果标签,如下图
+            var status = doc.InnerXml;
+            return status;
+        }
+    }
+}

+ 23 - 0
MicroServices/DopInterfacePlatform/DopInterfacePlatform.csproj

@@ -0,0 +1,23 @@
+<Project Sdk="Microsoft.NET.Sdk.Web">
+
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+    <Nullable>enable</Nullable>
+    <ImplicitUsings>enable</ImplicitUsings>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.21" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.21" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.21" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.21">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+    </PackageReference>
+    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
+    <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
+    <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.32.2" />
+    <PackageReference Include="System.ServiceModel.Http" Version="6.0.0" />
+  </ItemGroup>
+
+</Project>

+ 7 - 0
MicroServices/DopInterfacePlatform/DopInterfacePlatform.csproj.user

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Controller_SelectedScaffolderID>ApiControllerEmptyScaffolder</Controller_SelectedScaffolderID>
+    <Controller_SelectedScaffolderCategoryPath>root/Common/Api</Controller_SelectedScaffolderCategoryPath>
+  </PropertyGroup>
+</Project>

+ 25 - 0
MicroServices/DopInterfacePlatform/DopInterfacePlatform.sln

@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.4.33205.214
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DopInterfacePlatform", "DopInterfacePlatform.csproj", "{58B598BA-29FC-492E-A976-D271F3A842C8}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{58B598BA-29FC-492E-A976-D271F3A842C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{58B598BA-29FC-492E-A976-D271F3A842C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{58B598BA-29FC-492E-A976-D271F3A842C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{58B598BA-29FC-492E-A976-D271F3A842C8}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {7F2B40AE-DFBA-4D9F-B6CB-01281BA69379}
+	EndGlobalSection
+EndGlobal

+ 14 - 0
MicroServices/DopInterfacePlatform/DopInterfacePlatformContext.cs

@@ -0,0 +1,14 @@
+using DopInterfacePlatform.Entity;
+using Microsoft.EntityFrameworkCore;
+
+namespace DopInterfacePlatform
+{
+    public class DopInterfacePlatformContext: DbContext
+    {
+        public DbSet<InterfacePlatformLog> InterfacePlatformLog { get; set; }
+        public DopInterfacePlatformContext(DbContextOptions<DopInterfacePlatformContext> options)
+           : base(options)
+        {
+        }
+    }
+}

+ 49 - 0
MicroServices/DopInterfacePlatform/Entity/InterfacePlatformLog.cs

@@ -0,0 +1,49 @@
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Security.Principal;
+
+namespace DopInterfacePlatform.Entity
+{
+    [Table("InterfacePlatformLog")]
+    public class InterfacePlatformLog
+    {
+        [Key]
+        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
+        public Int64 operatorcol_id { get; set; }
+
+        /// <summary>
+        /// Desc:
+        /// Default:
+        /// Nullable:False
+        /// </summary>           
+        public string operatorcol_ip { get; set; }
+
+        /// <summary>
+        /// Desc:调用入参
+        /// Default:
+        /// Nullable:True
+        /// </summary>           
+        public string operatorcol_request { get; set; }
+
+        /// <summary>
+        /// Desc:调用出参
+        /// Default:
+        /// Nullable:True
+        /// </summary>           
+        public string operatorcol_respone { get; set; }
+
+        /// <summary>
+        /// Desc:
+        /// Default:
+        /// Nullable:False
+        /// </summary>           
+        public DateTime operatorcol_time { get; set; }
+
+        /// <summary>
+        /// Desc:调用接口耗时,单位为毫秒
+        /// Default:
+        /// Nullable:False
+        /// </summary>           
+        public int operatorcol_duration { get; set; }
+    }
+}

+ 9 - 0
MicroServices/DopInterfacePlatform/Interface/IJwtService.cs

@@ -0,0 +1,9 @@
+using System.Security.Claims;
+
+namespace DopInterfacePlatform.Interface
+{
+    public interface IJwtService
+    {
+        string BuildToken(IEnumerable<Claim> claims, JwtOptions options);
+    }
+}

+ 55 - 0
MicroServices/DopInterfacePlatform/IpWhiteListMiddleware.cs

@@ -0,0 +1,55 @@
+using System.Net;
+
+namespace DopInterfacePlatform
+{
+    public class IpWhiteListMiddleware
+    {
+        private readonly RequestDelegate _next;
+        private readonly ILogger<IpWhiteListMiddleware> _logger;
+        private readonly string _adminSafeList;
+
+        public IpWhiteListMiddleware(
+            RequestDelegate next,
+            ILogger<IpWhiteListMiddleware> logger,
+            string adminSafeList)
+        {
+            _adminSafeList = adminSafeList;
+            _next = next;
+            _logger = logger;
+        }
+
+        public async Task Invoke(HttpContext context)
+        {
+            if (context.Request.Method != "GET")
+            {
+                var remoteIp = context.Connection.RemoteIpAddress;
+                _logger.LogDebug($"Request from Remote IP address: {remoteIp}");
+
+                string[] ip = _adminSafeList.Split(';');
+
+                var bytes = remoteIp.GetAddressBytes();
+                var badIp = true;
+                foreach (var address in ip)
+                {
+                    var testIp = IPAddress.Parse(address);
+                    if (testIp.GetAddressBytes().SequenceEqual(bytes))
+                    {
+                        badIp = false;
+                        break;
+                    }
+                }
+
+                if (badIp)
+                {
+                    _logger.LogInformation(
+                        $"Forbidden Request from Remote IP address: {remoteIp}");
+                    context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
+                    return;
+                }
+            }
+
+            await _next.Invoke(context);
+
+        }
+    }
+}

+ 28 - 0
MicroServices/DopInterfacePlatform/JWTExtensions.cs

@@ -0,0 +1,28 @@
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.IdentityModel.Tokens;
+using System.Text;
+
+namespace DopInterfacePlatform
+{
+    public static class JWTExtensions
+    {
+        public static AuthenticationBuilder AddJWTAuthentication(this IServiceCollection services, JwtOptions jwtOptions)
+        {
+            return services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
+                .AddJwtBearer(x =>
+                {
+                    x.TokenValidationParameters = new()
+                    {
+                        ValidateIssuer = true,//是否验证发行商
+                        ValidateAudience = true,//是否验证受众者
+                        ValidateLifetime = true,//是否验证失效时间
+                        ValidateIssuerSigningKey = true,//是否验证签名键
+                        ValidIssuer = jwtOptions.Issuer,
+                        ValidAudience = jwtOptions.Audience,
+                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.Key))
+                    };
+                });
+        }
+    }
+}

+ 25 - 0
MicroServices/DopInterfacePlatform/JwtOptions.cs

@@ -0,0 +1,25 @@
+namespace DopInterfacePlatform
+{
+    public class JwtOptions
+    {
+        /// <summary>
+        /// 签发者
+        /// </summary>
+        public string Issuer { get; set; }
+
+        /// <summary>
+        /// 接收者
+        /// </summary>
+        public string Audience { get; set; }
+
+        /// <summary>
+        /// 密钥
+        /// </summary>
+        public string Key { get; set; }
+
+        /// <summary>
+        /// 过期时间
+        /// </summary>
+        public int ExpireSeconds { get; set; }
+    }
+}

+ 108 - 0
MicroServices/DopInterfacePlatform/LogFilter.cs

@@ -0,0 +1,108 @@
+using DopInterfacePlatform.Entity;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Logging;
+using System.Diagnostics;
+
+namespace DopInterfacePlatform
+{
+    /// <summary>
+    /// 记录日志
+    /// </summary>
+    public class LogFilter : ActionFilterAttribute
+    {
+        // private IBusApiOperatorRepository api_operator_repository;
+
+        private Stopwatch stopwach { get; set; }
+        private string actionArguments { get; set; }
+        private Dictionary<string, object> keyValuePairs { set; get; }
+
+        private readonly DopInterfacePlatformContext _context;
+
+        public LogFilter(DopInterfacePlatformContext context)
+        {
+            _context = context;
+        }
+
+        public override void OnActionExecuting(ActionExecutingContext context)
+        {
+            base.OnActionExecuting(context);
+
+            //is not controller return
+            if (!(context.ActionDescriptor is ControllerActionDescriptor action))
+                return;
+            var request = context.HttpContext.Request;
+            //启动倒带方式
+            request.EnableBuffering();
+            if (request.Method.ToLower().Equals("post"))
+            {
+                request.Body.Position = 0;
+                using var requestReader = new StreamReader(request.Body);
+                var requestContent = requestReader.ReadToEnd();
+                request.Body.Position = 0;
+            }
+
+            stopwach = new Stopwatch();
+            stopwach.Start();
+            if(context.ActionArguments.Count>0)
+            {
+                actionArguments = context.ActionArguments.ToJsonString();
+            }
+            stopwach = new Stopwatch();
+            stopwach.Start();
+        }
+
+        public override void OnActionExecuted(ActionExecutedContext context)
+        {
+            base.OnActionExecuted(context);
+
+            //is not controller return
+            if (!(context.ActionDescriptor is ControllerActionDescriptor action))
+                return;
+
+            stopwach.Stop();
+            var time = stopwach.Elapsed;
+
+            // string url = context.HttpContext.Request.Host + context.HttpContext.Request.Path + context.HttpContext.Request.QueryString;
+            string logMethod = context.HttpContext.Request.Method;
+            dynamic result = context.Result.GetType().Name == "EmptyResult"
+                ? new { Value = "无返回结果" }
+                : context.Result as dynamic;
+            string res = "在返回结果前发生了异常";
+            try
+            {
+                if (result != null)
+                {
+                    res = Newtonsoft.Json.JsonConvert.SerializeObject(result.Value);
+                }
+            }
+            catch (System.Exception ex)
+            {
+                res = "日志未获取到结果,返回的数据无法序列化!" + ex.Message;
+            }
+
+            //转换ActionDescriptor 
+            string logController = context.RouteData.Values["Controller"].ToString();
+            var logAction = context.RouteData.Values["Action"].ToString();
+            var controllerActionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
+            var ipAddress = context.HttpContext.Connection.RemoteIpAddress.ToString();
+            if(logAction!="GetToken")
+            {
+                var model = new InterfacePlatformLog();
+                if (actionArguments == null)
+                {
+                    actionArguments = "";
+                }
+                model.operatorcol_time = DateTime.Now;
+                model.operatorcol_ip = ipAddress;
+                model.operatorcol_duration = (int)time.TotalSeconds * 1000;
+                model.operatorcol_request = $"{logController}-{logAction}-{logMethod}-{actionArguments}"; //调用入参
+                model.operatorcol_respone = res; //调用出参 
+
+                _context.InterfacePlatformLog.Add(model);
+                _context.SaveChanges();
+            }
+        }
+    }
+}

+ 66 - 0
MicroServices/DopInterfacePlatform/Program.cs

@@ -0,0 +1,66 @@
+using DopInterfacePlatform.Interface;
+using DopInterfacePlatform.Service;
+using Microsoft.EntityFrameworkCore;
+using Swashbuckle.AspNetCore.SwaggerGen;
+using WebApiTest;
+
+namespace DopInterfacePlatform
+{
+    public class Program
+    {
+        public static void Main(string[] args)
+        {
+            var builder = WebApplication.CreateBuilder(args);
+
+            // Add services to the container.
+
+            builder.Services.AddControllers();
+            builder.Services.AddScoped<ClientIpCheckActionFilter>(container =>
+            {
+                var loggerFactory = container.GetRequiredService<ILoggerFactory>();
+                var logger = loggerFactory.CreateLogger<ClientIpCheckActionFilter>();
+
+                return new ClientIpCheckActionFilter(builder.Configuration["IpWhiteList"], logger);
+            });
+            // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
+            builder.Services.AddEndpointsApiExplorer();
+            builder.Services.AddSwaggerGen();
+            builder.Services.AddScoped<IJwtService, JwtService>();
+            JwtOptions jwtOpt = builder.Configuration.GetSection("JWT").Get<JwtOptions>();
+            builder.Services.AddJWTAuthentication(jwtOpt);
+            builder.Services.Configure<SwaggerGenOptions>(c =>
+            {
+                c.AddAuthenticationHeader();
+            });
+
+            builder.Services.AddDbContext<DopInterfacePlatformContext>(opt =>
+               opt.UseSqlServer(builder.Configuration["ConnectionStrings:todoContext"]));
+
+
+            builder.Services.AddMvcCore(options =>
+            {
+                options.Filters.Add<LogFilter>();
+            }).AddApiExplorer();
+
+            var app = builder.Build();
+
+            // Configure the HTTP request pipeline.
+            if (app.Environment.IsDevelopment())
+            {
+                app.UseSwagger();
+                app.UseSwaggerUI();
+            }
+
+            app.UseHttpsRedirection();
+
+            app.UseAuthentication();//注意,一定得先启动这个
+            app.UseAuthorization();
+
+            app.UseMiddleware<IpWhiteListMiddleware>(builder.Configuration["IpWhiteList"]);
+
+            app.MapControllers();
+
+            app.Run();
+        }
+    }
+}

+ 31 - 0
MicroServices/DopInterfacePlatform/Properties/launchSettings.json

@@ -0,0 +1,31 @@
+{
+  "$schema": "https://json.schemastore.org/launchsettings.json",
+  "iisSettings": {
+    "windowsAuthentication": false,
+    "anonymousAuthentication": true,
+    "iisExpress": {
+      "applicationUrl": "http://localhost:24100",
+      "sslPort": 44393
+    }
+  },
+  "profiles": {
+    "DopInterfacePlatform": {
+      "commandName": "Project",
+      "dotnetRunMessages": true,
+      "launchBrowser": true,
+      "launchUrl": "swagger",
+      "applicationUrl": "https://localhost:7059;http://localhost:5036",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    },
+    "IIS Express": {
+      "commandName": "IISExpress",
+      "launchBrowser": true,
+      "launchUrl": "swagger",
+      "environmentVariables": {
+        "ASPNETCORE_ENVIRONMENT": "Development"
+      }
+    }
+  }
+}

+ 21 - 0
MicroServices/DopInterfacePlatform/Service/JwtService.cs

@@ -0,0 +1,21 @@
+using DopInterfacePlatform.Interface;
+using Microsoft.IdentityModel.Tokens;
+using System.IdentityModel.Tokens.Jwt;
+using System.Security.Claims;
+using System.Text;
+
+namespace DopInterfacePlatform.Service
+{
+    public class JwtService : IJwtService
+    {
+        public string BuildToken(IEnumerable<Claim> claims, JwtOptions options)
+        {
+            //过期时间
+            TimeSpan timeSpan = TimeSpan.FromSeconds(options.ExpireSeconds);//token过期时间
+            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(options.Key));//加密的token密钥
+            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);//签名证书,其值为securityKey和HmacSha256Signature算法
+            var tokenDescriptor = new JwtSecurityToken(options.Issuer, options.Audience, claims, expires: DateTime.Now.Add(timeSpan), signingCredentials: credentials);//表示jwt token的描述信息,其值包括Issuer签发方,Audience接收方,Claims载荷,过期时间和签名证书
+            return new JwtSecurityTokenHandler().WriteToken(tokenDescriptor);//使用该方法转换为字符串形式的jwt token返回
+        }
+    }
+}

+ 610 - 0
MicroServices/DopInterfacePlatform/StringHelper.cs

@@ -0,0 +1,610 @@
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System.Collections;
+using System.Text;
+using System.Xml;
+
+namespace DopInterfacePlatform
+{
+    public static class StringHelper
+    {
+        private static int[] numbers = new[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+
+        /// <summary>
+        /// 随机字符串数组集合
+        /// </summary>
+        private static readonly string[] NonceStrings = new string[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+
+        /// <summary>
+        /// 四舍五入取整数部分
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static int StringToIntMathRound(this object @this)
+        {
+            string s_this = @this.ToString();
+            int i_result = 0;
+            if (s_this.Contains("."))
+            {
+                var tS =s_this.Split(".");
+                i_result = Convert.ToInt32(tS[0]);
+                if (Convert.ToInt32(tS[1].Substring(0, 1)) > 4)
+                {
+                    i_result += 1;
+                }
+            }
+            else
+            {
+                i_result = Convert.ToInt32(@this);
+            }
+
+            return i_result;
+        }
+        
+        /// <summary>
+        /// 生成指定长度的随机字符串
+        /// </summary>
+        /// <returns></returns>
+        public static string CreateNonceStr(this int stringLenght)
+        {
+            Random random = new Random();
+            var sb = new StringBuilder();
+            var length = NonceStrings.Length;
+            for (int i = 0; i < stringLenght; i++)
+            {
+                //通过random获得的随机索引到,NonceStrings数组中获取对应数组值
+                sb.Append(NonceStrings[random.Next(length - 1)]);
+            }
+            return sb.ToString();
+        }
+
+        
+        /// <summary>
+        /// 获取指定长度的随机数
+        /// </summary>
+        /// <returns></returns>
+        public static string GetRandom(this string @prexString, int lenght)
+        {
+            string result = prexString;
+            Random rd = new Random();
+            for (int i = 0; i < lenght - prexString.Length; i++)
+            {
+                int RandKey = rd.Next(100, 999);
+                var index = RandKey % 10;
+                result += numbers[index].ToString();
+            }
+            return result;
+        }
+
+
+        /// <summary>
+        /// decimal取指定位小数返回
+        /// </summary>
+        /// <param name="this"></param>
+        /// <param name="decimals"></param>
+        /// <returns></returns>
+        public static decimal DecimalsFormat(this decimal @this,int decimals=2)
+        {
+            return Math.Round(@this, decimals);
+        }
+
+        /// <summary>
+        /// 涉及到金额部分把最后的0 去掉
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static string CashFormat(this object @this)
+        {
+            string cashValue = @this.ToString();
+            if (cashValue != null && cashValue.Contains(".")) //
+            {
+                while (cashValue.EndsWith("0"))
+                {
+                    cashValue = cashValue.Substring(0, cashValue.Length - 1);
+                }
+
+                if (cashValue.EndsWith("."))
+                    cashValue = cashValue.Substring(0, cashValue.Length - 1);
+            }
+
+            return cashValue;
+        }
+
+        /// <summary>
+        /// 判断是否为空
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static bool IsNullOrWhiteSpace(this string @this)
+        {
+            if (@this == null) return true;
+            return string.IsNullOrWhiteSpace(@this.Trim()) || @this == "null";
+        }
+
+        /// <summary>
+        /// tostring的另一个版本,当是null字符串时返回空串
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static string ToSelfOrNullString(this string @this)
+        {
+            if (@this == null) return "";
+            return string.IsNullOrWhiteSpace(@this.Trim()) || @this == "null" ? "" : @this;
+        }
+
+        public static Hashtable GetProperties<T>(this T @userInfo)
+        {
+            Hashtable hashtable = new Hashtable();
+            foreach (System.Reflection.PropertyInfo p in userInfo.GetType().GetProperties())
+            {
+                hashtable.Add(p.Name, p.GetValue(userInfo));
+            }
+            return hashtable;
+        }
+        /// <summary>
+        /// 去掉Emoji表情
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static string RemoveEmoji(this string @this)
+        {
+            foreach (var strTmp in @this)
+            {
+                byte[] bts = Encoding.UTF32.GetBytes(strTmp.ToString());
+                
+                if (bts[0].ToString() == "253"&& bts[1].ToString() == "255")
+                {
+                    @this = @this.Replace(strTmp.ToString(), "");
+                }
+                    
+            }
+            return @this;
+        }
+
+
+        /// <summary>
+        /// 将Json字符串转换为对应的Json对象
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static T ToJsonObject<T>(this string @this)
+        {
+            return JsonConvert.DeserializeObject<T>(@this);
+        }
+        public static string DateTimeOfDayWeek(this string @this)
+        {
+            try
+            {
+
+                return ((int) Convert.ToDateTime(@this).DayOfWeek).ToString();
+            }
+            catch (Exception e)
+            {
+                return "";
+            }
+        }
+
+        public static string YuanToFen(this string money)
+        {
+            return Convert.ToInt64(Convert.ToDecimal(money) * 100).ToString();
+        } 
+        
+        public static string FenToYuan(this int money)
+        {
+            return (Convert.ToDecimal(money)/100).ToString();
+        }
+        /// <summary>
+        /// 将对象转换为string字符串
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static string ToJsonString(this object @this)
+        {
+            return JsonConvert.SerializeObject(@this);
+        }
+
+        /// <summary>
+        /// 排序字段
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static Dictionary<string, object> SortDictionary(this Dictionary<string, object> @this)
+        {
+            Dictionary<string, object> keyValues = new Dictionary<string, object>();
+            foreach (var item in @this)
+            {
+                if (item.Value == null || item.Value.ToString() == "")
+                {
+                    continue;
+                }
+                if(item.Key== "PatType")
+                {
+
+                }
+                if (item.Value.GetType().Name == "JObject")
+                {
+                    JObject j_object = item.Value as JObject;
+                    keyValues = keyValues.Concat(j_object.JObjectToDictionary()).ToDictionary(k => k.Key, v => v.Value);
+                }
+                else
+                {
+                    keyValues.Add(item.Key, item.Value);
+                }
+            }
+            return keyValues.OrderBy(p => p.Key).Where(d => d.Value != null).ToDictionary(p => p.Key, o => o.Value);
+        }
+
+        /// <summary>
+        /// JObject to Dictionary<string, object>
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        private static Dictionary<string, object> JObjectToDictionary(this JObject @this)
+        {
+            Dictionary<string, object> keyValues = new Dictionary<string, object>();
+            foreach (var item in @this)
+            {
+                keyValues.Add(item.Key, item.Value);
+
+                //不考虑有多层的情况
+                //if (item.Value.GetType().Name == "JObject")
+                //{
+                //    JObject j_object = item.Value as JObject;
+                //    //还有子项目
+                //    keyValues = keyValues.Concat(j_object.JObjectToDictionary()).ToDictionary(k => k.Key, v => v.Value);
+                //}
+                //else
+                //{
+                //    keyValues.Add(item.Key, item.Value);
+                //}
+            }
+            return keyValues;
+        }
+
+        /// <summary>
+        /// 转换成签名串
+        /// </summary>
+        /// <param name="this"></param>
+        /// <returns></returns>
+        public static string ToSignString(this object @this)
+        {
+            var objName = @this.GetType().Name;
+            if (objName == "DateTime")
+            {
+                return Convert.ToDateTime(@this).ToString("yyyy-MM-dd HH:mm:ss");
+            }
+            else
+            {
+                return @this.ToString();
+            }
+        }
+
+        /// <summary>
+        /// BASE64编码
+        /// </summary>
+        /// <param name="un_code_string"></param>
+        /// <param name="code_type"></param>
+        /// <returns></returns>
+        public static string EncodeBase64(this string un_code_string,string code_type= "utf-8")
+        {
+            byte[] bytes = Encoding.GetEncoding(code_type).GetBytes(un_code_string);
+            string encode;
+            try
+            {
+                encode = Convert.ToBase64String(bytes);
+            }
+            catch
+            {
+                encode = un_code_string;
+            }
+            return encode;
+        }
+        /// <summary>
+        /// BASE64解码
+        /// </summary>
+        /// <param name="code_string"></param>
+        /// <param name="code_type"></param>
+        /// <returns></returns>
+        public static string DecodeBase64(this string code_string,string code_type = "utf-8")
+        {
+            byte[] bytes = Convert.FromBase64String(code_string);
+            string decode;
+            try
+            {
+                decode = Encoding.GetEncoding(code_type).GetString(bytes);
+            }
+            catch
+            {
+                decode = code_string;
+            }
+            return decode;
+        }
+
+
+        /// <summary>
+        /// xml格式的字符串转换成对象
+        /// </summary>
+        /// <param name="xmlStr"></param>
+        /// <returns></returns>
+        public static T XmlToObject<T>(this string xmlStr) where T : new()
+        {
+            try
+            {
+                T obj = new T();
+                var repType = typeof(T);
+                XmlDocument document = new XmlDocument();
+                document.LoadXml(xmlStr);    //加载Xml文件  
+                XmlElement node = document.DocumentElement; //xml的根标签
+                var properties = repType.GetProperties();
+                foreach (var itemProp in properties)
+                {
+                    #region current type is List
+                    if (itemProp.PropertyType.FullName.Contains("System.Collections.Generic.List"))
+                    {
+                        object array = new object();
+                        var arryLength = 0;
+                        var notNullLength = 0;
+                        var arryType = itemProp.PropertyType.UnderlyingSystemType;
+
+                        var objList = itemProp.GetValue(obj, null) as System.Collections.IEnumerable;
+                        var enumt = objList.GetEnumerator();
+                        //enumt.
+                        var currentType = itemProp.PropertyType.GetGenericArguments()[0];
+
+                        foreach (XmlNode xmlitem in node.ChildNodes)
+                        {
+                            if (xmlitem.Name == itemProp.Name)
+                            {
+                                arryLength++;
+                            }
+                        }
+                        if (arryLength > 0)
+                        {
+                            var arrayModel = arryType.InvokeMember("Set", System.Reflection.BindingFlags.CreateInstance, null, array, new object[] { arryLength }) as System.Collections.IList;
+                            foreach (XmlNode item in node.ChildNodes)
+                            {
+                                //current type is array
+                                if (item.Name == itemProp.Name)
+                                {
+                                    var model = currentType.Assembly.CreateInstance(currentType.FullName); // arryType.GetElementType().Assembly.CreateInstance(currentType.FullName);
+                                    SetArray(item.ChildNodes, model, true);
+                                    arrayModel.Add(model);
+                                    //arrayModel[notNullLength] = model;
+                                    notNullLength++;
+                                }
+                            }
+                            itemProp.SetValue(obj, arrayModel, null);
+                        }
+
+                        continue;
+                    }
+                    #endregion
+                    var baseType = itemProp.PropertyType.BaseType.Name;
+                    if (baseType == "Array")
+                    {
+                        #region Current type is Array
+                        object array = new object();
+                        var arryLength = 0;
+                        var notNullLength = 0;
+                        var arryType = itemProp.PropertyType.UnderlyingSystemType;
+
+                        foreach (XmlNode xmlitem in node.ChildNodes)
+                        {
+                            if (xmlitem.Name == itemProp.Name && xmlitem.ChildNodes!=null && xmlitem.ChildNodes.Count>0)
+                            {
+                                arryLength++;
+                            }
+                        }
+                        if (arryLength > 0)
+                        {
+                            var arrayModel = arryType.InvokeMember("Set", System.Reflection.BindingFlags.CreateInstance, null, array, new object[] { arryLength }) as System.Collections.IList;
+                            foreach (XmlNode item in node.ChildNodes)
+                            {
+                                //current type is array
+                                if (item.Name == itemProp.Name && item.ChildNodes!=null && item.ChildNodes.Count>0)
+                                {
+                                    var model = arryType.GetElementType().Assembly.CreateInstance(arryType.GetElementType().FullName);
+                                    SetArray(item.ChildNodes, model);
+                                    arrayModel[notNullLength] = model;
+                                    notNullLength++;
+                                }
+                            }
+                            itemProp.SetValue(obj, arrayModel, null);
+                        }
+                        #endregion
+                    }
+                    else
+                    {
+                        #region Current type isn't Array
+                        foreach (XmlNode item in node.ChildNodes)
+                        {
+                            #region Current type is Number
+                            if (itemProp.Name == item.Name && (itemProp.PropertyType == typeof(long) || itemProp.PropertyType == typeof(int) || itemProp.PropertyType == typeof(string)))
+                            {
+                                if (itemProp.PropertyType == typeof(int) || itemProp.PropertyType == typeof(long))
+                                {
+                                    if (!string.IsNullOrEmpty(item.InnerText))
+                                    {
+                                        if (itemProp.PropertyType == typeof(int))
+                                        {
+                                            itemProp.SetValue(obj, Convert.ToInt32(item.InnerText), null);
+                                        }
+                                        else
+                                        {
+                                            itemProp.SetValue(obj, Convert.ToInt64(item.InnerText), null);
+                                        }
+
+                                    }
+                                    else
+                                    {
+                                        itemProp.SetValue(obj, 0, null);
+                                    }
+                                }
+                                else
+                                {
+                                    itemProp.SetValue(obj, item.InnerText, null);
+                                }
+                            }
+                            #endregion
+
+                            #region Current type is Model
+                            if (itemProp.PropertyType != typeof(long) && itemProp.PropertyType != typeof(string) && itemProp.PropertyType != typeof(int) && itemProp.PropertyType.Name == item.Name && item.HasChildNodes && item.FirstChild.NodeType == System.Xml.XmlNodeType.Element)
+                            {
+                                var modelType = itemProp.PropertyType.UnderlyingSystemType;
+                                var model = modelType.Assembly.CreateInstance(modelType.FullName);
+                                SetArray(item.ChildNodes, model);
+                                itemProp.SetValue(obj, model, null);
+                            }
+                            #endregion
+                        }
+                        #endregion
+
+                    }
+                }
+                repType = obj.GetType();
+                return obj;
+            }
+            catch (Exception ex)
+            {
+                throw ex;
+            }
+        }
+
+        #region Set array value
+        private static Object SetArray(XmlNodeList xmlNodeList, object obj, bool isList = false)
+        {
+            try
+            {
+                var type = obj.GetType();
+                var properties = type.GetProperties();
+                foreach (var itemProp in properties)
+                {
+                    //if (isList)
+                    if (itemProp.PropertyType.FullName.Contains("System.Collections.Generic.List"))
+                    {
+                        #region Current type is List
+                        object array = new object();
+                        var arryLength = 0;
+                        var notNullLength = 0;
+                        var arryType = itemProp.PropertyType.UnderlyingSystemType;
+                        var currentType = itemProp.PropertyType.GetGenericArguments()[0];
+                        foreach (XmlNode xmlitem in xmlNodeList)
+                        {
+                            if (xmlitem.Name == itemProp.Name)
+                            {
+                                arryLength++;
+                            }
+                        }
+
+                        if (arryLength > 0)
+                        {
+                            var arrayModel = arryType.InvokeMember("Set", System.Reflection.BindingFlags.CreateInstance, null, array, new object[] { arryLength }) as System.Collections.IList;
+                            foreach (XmlNode item in xmlNodeList)
+                            {
+                                //current type is array
+                                if (item.Name == itemProp.Name)
+                                {
+                                    var model = currentType.Assembly.CreateInstance(currentType.FullName); // var model = arryType.GetElementType().Assembly.CreateInstance(arryType.GetElementType().FullName);
+                                    SetArray(item.ChildNodes, model, true);
+                                    arrayModel.Add(model);
+                                    notNullLength++;
+
+                                }
+                            }
+                            itemProp.SetValue(obj, arrayModel, null);
+                        }
+                        #endregion
+                        return obj;
+                    }
+
+
+                    var baseType = itemProp.PropertyType.BaseType.Name;
+                    if (baseType == "Array")
+                    {
+                        #region Current type is Array
+                        object array = new object();
+                        var arryLength = 0;
+                        var notNullLength = 0;
+                        var arryType = itemProp.PropertyType.UnderlyingSystemType;
+                        foreach (XmlNode xmlitem in xmlNodeList)
+                        {
+                            if (xmlitem.Name == itemProp.Name)
+                            {
+                                arryLength++;
+                            }
+                        }
+
+                        if (arryLength > 0)
+                        {
+                            var arrayModel = arryType.InvokeMember("Set", System.Reflection.BindingFlags.CreateInstance, null, array, new object[] { arryLength }) as System.Collections.IList;
+                            foreach (XmlNode item in xmlNodeList)
+                            {
+                                //current type is array
+                                if (item.Name == itemProp.Name)
+                                {
+                                    var model = arryType.GetElementType().Assembly.CreateInstance(arryType.GetElementType().FullName);
+                                    SetArray(item.ChildNodes, model);
+                                    arrayModel[notNullLength] = model;
+                                    notNullLength++;
+
+                                }
+                            }
+                            itemProp.SetValue(obj, arrayModel, null);
+                        }
+                        #endregion
+                    }
+                    else
+                    {
+                        foreach (XmlNode item in xmlNodeList)
+                        {
+                            #region Current type is Number
+                            if (itemProp.Name == item.Name && (itemProp.PropertyType == typeof(long) || itemProp.PropertyType == typeof(int) || itemProp.PropertyType == typeof(string)))
+                            {
+                                if (itemProp.PropertyType == typeof(int) || itemProp.PropertyType == typeof(long))
+                                {
+                                    if (!string.IsNullOrEmpty(item.InnerText))
+                                    {
+                                        if (itemProp.PropertyType == typeof(int))
+                                        {
+                                            itemProp.SetValue(obj, Convert.ToInt32(item.InnerText), null);
+                                        }
+                                        else
+                                        {
+                                            itemProp.SetValue(obj, Convert.ToInt64(item.InnerText), null);
+                                        }
+                                    }
+                                    else
+                                    {
+                                        itemProp.SetValue(obj, 0, null);
+                                    }
+                                }
+                                else
+                                {
+                                    itemProp.SetValue(obj, item.InnerText, null);
+                                }
+                            }
+                            #endregion
+
+                            #region Current type is Model
+                            if (itemProp.PropertyType != typeof(long) && itemProp.PropertyType != typeof(int) && itemProp.PropertyType != typeof(string) && itemProp.PropertyType.Name == item.Name && item.HasChildNodes && item.FirstChild.NodeType == System.Xml.XmlNodeType.Element)
+                            {
+                                var modelType = itemProp.PropertyType.UnderlyingSystemType;
+                                var model = modelType.Assembly.CreateInstance(modelType.FullName);
+                                SetArray(item.ChildNodes, model);
+                                itemProp.SetValue(obj, model, null);
+                            }
+                            #endregion
+                        }
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                throw new Exception(ex.Message);
+            }
+            return obj;
+        }
+        #endregion
+    }
+}

+ 44 - 0
MicroServices/DopInterfacePlatform/SwaggerGenOptionsExtensions.cs

@@ -0,0 +1,44 @@
+using Microsoft.OpenApi.Models;
+using Swashbuckle.AspNetCore.SwaggerGen;
+
+namespace DopInterfacePlatform
+{
+    public static class SwaggerGenOptionsExtensions
+    {
+        /// <summary>
+        /// 为swagger增加Authentication报文头
+        /// </summary>
+        /// <param name="option"></param>
+        public static void AddAuthenticationHeader(this SwaggerGenOptions option)
+        {
+            option.AddSecurityDefinition("Authorization",
+                new OpenApiSecurityScheme
+                {
+                    Description = "Authorization header. \r\nExample:Bearer 12345ABCDE",
+                    Name = "Authorization",
+                    In = ParameterLocation.Header,
+                    Type = SecuritySchemeType.ApiKey,
+                    Scheme = "Authorization"
+                }
+                ); ;
+
+            option.AddSecurityRequirement(new OpenApiSecurityRequirement()
+            {
+                {
+                    new OpenApiSecurityScheme
+                    {
+                        Reference=new OpenApiReference
+                        {
+                            Type=ReferenceType.SecurityScheme,
+                            Id="Authorization"
+                        },
+                        Scheme="oauth2",
+                        Name="Authorization",
+                        In=ParameterLocation.Header,
+                    },
+                    new List<string>()
+                }
+            });
+        }
+    }
+}

+ 13 - 0
MicroServices/DopInterfacePlatform/WeatherForecast.cs

@@ -0,0 +1,13 @@
+namespace DopInterfacePlatform
+{
+    public class WeatherForecast
+    {
+        public DateTime Date { get; set; }
+
+        public int TemperatureC { get; set; }
+
+        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
+
+        public string? Summary { get; set; }
+    }
+}

+ 8 - 0
MicroServices/DopInterfacePlatform/appsettings.Development.json

@@ -0,0 +1,8 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft.AspNetCore": "Warning"
+    }
+  }
+}

+ 19 - 0
MicroServices/DopInterfacePlatform/appsettings.json

@@ -0,0 +1,19 @@
+{
+  "Logging": {
+    "LogLevel": {
+      "Default": "Information",
+      "Microsoft.AspNetCore": "Warning"
+    }
+  },
+  "AllowedHosts": "*",
+  "JWT": {
+    "Issuer": "zzy2025@qq.com",
+    "Audience": "zzy2025@qq.com",
+    "Key": "A86DA130-1B95-4748-B3B2-1B6AA9F2F743", //加密密钥
+    "ExpireSeconds": 600 //密钥过期时间
+  },
+  "IpWhiteList": "192.168.1.5;::1",
+  "ConnectionStrings": {
+    "todoContext": "Server=123.60.180.165;Database=DopInterfacePlatform;uid=sa;pwd=5h3n9)uN;Trusted_Connection=false;TrustServerCertificate=True"
+  }
+}