<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      soulsoft

      我們正在探索 Cangjie 與 ASP.NET Core 的深度融合,致力于打造:
      ? 現(xiàn)代化:基于最新 .NET 技術(shù)棧的開發(fā)范式
      ? 輕量級(jí):低侵入設(shè)計(jì),零冗余依賴
      ? 可擴(kuò)展:模塊化架構(gòu),按需組合功能
      ? 可插拔:通過 gitcode 配置快速集成

      誠邀志同道合的開發(fā)者加入 Soulsoft 組織,共同構(gòu)建:
      ?? 標(biāo)準(zhǔn)化組件庫
      ?? 統(tǒng)一技術(shù)生態(tài)
      ?? 開源社區(qū)協(xié)作平臺(tái)

      內(nèi)置模塊

      模塊名稱 描述 必要性 鏈接
      soulsoft_asp_http HTTP核心功能 必需 鏈接
      soulsoft_asp_mvc MVC 可選 鏈接
      soulsoft_asp_routing 路由與終結(jié)點(diǎn) 必需 鏈接
      soulsoft_asp_hosting Web主機(jī) 必需 鏈接
      soulsoft_asp_staticfiles 靜態(tài)文件支持 可選 鏈接
      soulsoft_asp_healthchecks 健康檢查中間件 可選 鏈接
      soulsoft_asp_authentication 身份認(rèn)證中間件 可選 鏈接
      soulsoft_asp_authentication_jwtbearer Jwt身份認(rèn)證方案 可選 鏈接
      soulsoft_asp_authorization 授權(quán)中間件 可選 鏈接
      soulsoft_security_claims 身份聲明 可選 鏈接
      soulsoft_extensions_hosting 通用主機(jī) 可選 鏈接
      soulsoft_extensions_logging 日志 可選 鏈接
      soulsoft_extensions_options 選項(xiàng) 必需 鏈接
      soulsoft_extensions_injection 依賴注入 可選 鏈接
      soulsoft_extensions_healthchecks 健康檢查服務(wù) 可選 鏈接
      soulsoft_extensions_configuration 配置管理 可選 鏈接

      《依賴注入》

      1. 基本使用
      //創(chuàng)建容器構(gòu)建器
      let services = ServiceCollection()
      //注冊(cè)單例服務(wù)
      services.addSingleton<IDbConnection, DbConnection>()
      //可以使用工廠模式,來規(guī)避反射
      services.addSingleton<IDbConnection>(){ sp =>
          DbConnection()
      }
      //構(gòu)建容器
      let provider = services.build()
      //解析服務(wù)
      let connection = provider.getOrThrow<IDbConnection>()
      //解析未注冊(cè)的服務(wù),但是依賴容器中的服務(wù)
      let context = ActivatorUtilities.createInstance<DbContext>(provider)
      
      1. 生命周期
      周期 說明
      Singleton 單例:一個(gè)根容器及其子容器,只創(chuàng)建一個(gè)實(shí)列
      Scoped 作用域:同一個(gè)作用域只創(chuàng)建一個(gè)實(shí)列,生命周期由業(yè)務(wù)定義
      Transient 瞬時(shí):每次解析都是一個(gè)新的實(shí)列
      let services = ServiceCollection()
      services.addScoped<IDbConnection, DbConnection>()
      let provider = services.build()//根容器
      //創(chuàng)建作用域
      try (scope = provider.createScope()){
          //子容器
          let connection = scope.services.getOrThrow<IDbConnection>()
      }
      //作用域結(jié)束時(shí)會(huì)釋放該作用域解析的非單例的實(shí)列(需要實(shí)現(xiàn)Resource接口)。
      

      注意:通過ServiceCollection直接構(gòu)建的稱為根容器,通過ServiceProvider創(chuàng)建的scope關(guān)聯(lián)的容器稱為子容器。根容器無法解析非單例的服務(wù)。

      《選項(xiàng)》

      選項(xiàng)是對(duì)依賴注入模塊的擴(kuò)展和補(bǔ)充,用于統(tǒng)一框架設(shè)計(jì)者和使用者之間的約定,設(shè)計(jì)者通過configure方法設(shè)置默認(rèn)值,使用者使用者通過configureAfter方法修改默認(rèn)值

      1. 基本使用
      //定義一個(gè)選項(xiàng)
      public class DbConnectionOptions {
          var connectionString = "default"
      }
      //定義容器
      let services = ServiceCollection()
      services.configureAfter<DbConnectionOptions>{configureOptions =>
          configureOptions.connectionString = "2.1"
      }
      services.configureAfter<DbConnectionOptions>{configureOptions =>
          configureOptions.connectionString = "2.2"
      }
      services.configure<DbConnectionOptions>{configureOptions =>
          configureOptions.connectionString = "1.1"
      }
      services.configure<DbConnectionOptions>{configureOptions =>
          configureOptions.connectionString = "1.2"
      }
      //構(gòu)建容器
      let provider = services.build()
      //解析選項(xiàng)
      let options = provider.getOrThrow<IOptions<DbConnectionOptions>>()
      println(options.value.connectionString)//輸出2.2
      

      注意:上面的版本號(hào)即執(zhí)行順序,無論解析多少次每個(gè)lambda函數(shù)只執(zhí)行一次

      1. 命名選項(xiàng)
      let services = ServiceCollection()
      services.configure<DbConnectionOptions>("tenant1"){configureOptions =>
          configureOptions.connectionString = "1.1"
      }
      services.configure<DbConnectionOptions>("tenant2"){configureOptions =>
          configureOptions.connectionString = "1.2"
      }
      let provider = services.build()
      let options = provider.getOrThrow<IOptions<DbConnectionOptions>>()
      println(options.value.connectionString)
      println(options.get("tenant1").connectionString)
      println(options.get("tenant2").connectionString)
      

      命名選項(xiàng)在多租戶,多架構(gòu)場景下非常有用

      《配置》

      配置支持多數(shù)據(jù)源(命令行參數(shù),環(huán)境變量,json)和自定義數(shù)據(jù)來源。

      main(args: Array<String>) {
          let configurationBuilder = ConfigurationManager()
          //添加命令行參數(shù)
          configurationBuilder.addArgVars(args)
          //添加“asp_”開頭的環(huán)境變量
          configurationBuilder.addEnvVars("asp")
          //添加json配置
          configurationBuilder.addJsonFile("./appsettings.json", true)
          let configuration = configurationBuilder.build()
          println(configuration["help"])
          println(configuration["port"])
          //循環(huán)處理所有l(wèi)ogging:logLevel節(jié)點(diǎn)下的直接屬性
          for (pattern in configuration.getSection("logging:logLevel").getChildren()) {
              println("${pattern.key}=${pattern.value}")
          }
          return 0
      }
      

      appsettings.json

      {
          "logging": {
              "logLevel": {
                  "default": "Info",
                  "soulsoft": "Error"
              }
          }
      }
      

      《日志》

      日志模塊也是應(yīng)用開發(fā)過程中必備可卻的組件,日志模塊內(nèi)置了控制臺(tái)和文件提供程序,同樣也支持自定義日志提供程序

      1. 基本使用
      let logFactory = LoggingBuilder()
          .addFile()
          .addConsole()
          .build()
      let logger = logFactory.createLogger("soulsoft.logging.test")    
      logger.info("hello")
      
      1. 使用日志過濾器
      let logFactory = LoggingBuilder()
          .addFile()
          .addConsole()
          .addFilter{providerName, categoryName, logLevel => 
              (providerName == "file" && logLevel >= LogLevel.Error) || 
              (providerName == "console" && logLevel >= LogLevel.Info)
          }
          .build()
      let logger = logFactory.createLogger("soulsoft.logging.test")    
      logger.info("hello")//文件中不打印,控制臺(tái)中打印
      logger.error("hello")//文件中打印,控制臺(tái)中打印
      
      1. 使用配置文件過濾
      • file提供程序過濾規(guī)則:以asp結(jié)尾的日志,只打印Warn及以上級(jí)別的日志
      • console提供程序過濾規(guī)則:以asp開頭的日志,只打印Info及以上級(jí)別的日志
      • 默認(rèn)過濾規(guī)則:除上述之外打印Info及以上級(jí)別的日志
      //創(chuàng)建配置
      let configurationBuilder = ConfigurationManager()
      configurationBuilder.addJsonFile("./appsettings.json", true)
      let configuration = configurationBuilder.build()
      //創(chuàng)建日志工廠
      let logFactory = LoggingBuilder()
          .addFile()
          .addConsole()
          .addConfiguration(configuration.getSection("logging"))
          .build()
      //測試
      logFactory.createLogger("soulsoft.asp").info("hello")    
      logFactory.createLogger("asp.soulsoft").info("hello")  
      logFactory.createLogger("cangjie").info("hello")    
      

      ./appsettings.json

      {
          "logging": {
              "logLevel": {
                  "default": "Info"
              },
              "file": {
                  "logLevel": {
                      "*.asp": "Warn"
                  }
              },
              "console": {
                  "logLevel": {
                      "asp.*": "Info"
                  }
              }
          }
      }
      

      《通用主機(jī)》

      通用主機(jī)整合了上述所有模塊,用于處理定時(shí)任務(wù)和消息隊(duì)列

      1. 創(chuàng)建一個(gè)工人和選項(xiàng)
      
      public class TestWorkerOptions {
          public var delay = 10
      }
      
      public class TestWorker <: BackgroundService {
          private let _logger: ILogger
      
          public TestWorker(let _options: IOptions<TestWorkerOptions>, let _env: IHostEnvironment, let _logFactory: ILoggerFactory) {
              _logger = _logFactory.createLogger<TestWorker>()
          }
          
          public func run() {
      
              while (!Thread.currentThread.hasPendingCancellation) {
                  //不同環(huán)境,執(zhí)行不同邏輯
                  if(_env.environmentName == "prod") {
                      logger.info("working...")
                  }else {
                      logger.info("hello...")
                  }
                  sleep(_options.value.delay * Duration.second)
              }
          }
      }
      
      1. 定義一個(gè)擴(kuò)展
      extend ServiceCollection{
      
          public func addTestWorker(configureOptions: (TestWorkerOptions) -> Unit): ServiceCollection {
              this.addHostedService<TestWorker>()
              this.configure<TestWorkerOptions>(configureOptions)
          }
      }
      
      1. 啟動(dòng)主機(jī)
      main(args: Array<String>) {
          let builder = Host.createBuilder(args)
          
          //注冊(cè)我們的后臺(tái)服務(wù)
          builder.services.addTestWorker()
          
          let host = builder.build()
          
          host.run()
          return 0
      }
      
      • 主機(jī)內(nèi)置了IHostEnvironment服務(wù),可以通過解析它來區(qū)分開發(fā)環(huán)境還是生成環(huán)境
      • 可以通過asp_environment環(huán)境變量或者--environment=test命令行參數(shù)來修改環(huán)境名

      《Web主機(jī)》

      web主機(jī)實(shí)現(xiàn)了通用主機(jī),并且在此基礎(chǔ)上擴(kuò)展了http協(xié)議,內(nèi)置請(qǐng)求管道來處理請(qǐng)求邏輯。soulsoft組織提供了了大量的中間件供開發(fā)者使用

      啟動(dòng)一個(gè)支持靜態(tài)文件的web主機(jī)

      main(args: Array<String>) {
          let builder = WebHost.createBuilder(args)
          let host = builder.build()
      
          //當(dāng)請(qǐng)求網(wǎng)站根路徑(/)時(shí),負(fù)責(zé)查找并返回index.html頁面
          host.useDefaultFiles()
      
          //該中間件負(fù)責(zé)去wwwroot中查找并返回/xxx.(html|css|js|...)文件
          host.useStaticFiles()
      
          host.run()
      
          return 0
      }
      

      啟動(dòng)一個(gè)支持動(dòng)態(tài)資源的web主機(jī)

      main(args: Array<String>) {
          let builder = WebHost.createBuilder(args)
      
          builder.services.addRouting()//注冊(cè)路由中間件需要的服務(wù)
      
          let host = builder.build()
      
          //useEndpoints:會(huì)注冊(cè)兩個(gè)中間件,一個(gè)負(fù)責(zé)路由,一個(gè)負(fù)責(zé)執(zhí)行終結(jié)點(diǎn)
          host.useEndpoints { endpoints =>
              endpoints.mapGet("hello") {
                  context => context.response.write("hello:soulsoft")
              }   
          }
          host.run()
          return 0
      }
      
      • 路由中間件(EndpointRoutingMiddleware):負(fù)責(zé)根據(jù)用戶輸入的uri查找對(duì)應(yīng)的Endpoint并放到HttpContext上(調(diào)用setEndpoint
      • 終結(jié)點(diǎn)中間件(EndpointMiddleware):通過調(diào)用HttpContext上面的getEndpoint()方法獲取終結(jié)點(diǎn),如果存在Endpoint將會(huì)執(zhí)行它

      健康檢查中間件

      main(args: Array<String>) {
          let builder = WebHost.createBuilder(args)
      
          builder.services.addHealthChecks()
              //添加一個(gè)健康檢查項(xiàng)
              .addCheck("self") {
                  //模擬隨機(jī)不健康效果
                  let random = Random()
                  if (random.nextInt32(10) % 2 == 0) {
                      HealthCheckResult.healthy()
                  } else {
                      HealthCheckResult.unhealthy()
                  }
              }
      
          let host = builder.build()
      
          host.useHealthChecks("/health")
      
          host.run()
      
          return 0
      }
      

      《身份認(rèn)證》

      Basic認(rèn)證方案

      我們?cè)谏矸菡J(rèn)證模塊下可以非常方便的實(shí)現(xiàn)一個(gè)認(rèn)證方案,比如Basic認(rèn)證方案。身份認(rèn)證模塊為我們處理好了認(rèn)證和授權(quán)流程

      public class BasicAuthenticationDefault {
          public static let scheme = "basic"
      }
      
      public class BasicAuthenticationOptions <: AuthenticationSchemeOptions {
          public var realm = "basic"
      }
      
      //定義basic認(rèn)證方案
      public class BasicAuthenticationHandler <: AuthenticationHandler<BasicAuthenticationOptions> {
          public init(options: IOptions<BasicAuthenticationOptions>, logger: ILoggerFactory) {
              super(options, logger)
          }
      
          public func handleAuthenticate() {
              if (let Some(authorization) <- this.context.request.headers.getFirst("Authorization")
                  .flatMap{f => fromBase64String(f.replace("Basic ", "")).flatMap{f=> String.fromUtf8(f)} }) {
                 
                  let secrets = authorization.split(":")
                  if (secrets.size == 2) {
                      let username = secrets[0]
                      let password = secrets[1]
                      this.logger.info("username:${username},password:${password}")  
                      //通過子容器來解析非單例的服務(wù):IResourceOwnerPasswordValidator  
                      let validator = this.context.services.getOrThrow<IResourceOwnerPasswordValidator>()
                      if (!validator.validate(username, password)) {
                          return AuthenticateResult.fail(Exception("Invalid username or password"))
                      }
                      let subject = ClaimsPrincipal()
                      let identity = ClaimsIdentity(this.scheme.name)
                      identity.addClaim(Claim("username",username))
                      identity.addClaim(Claim("password",password))
                      subject.addIdentity(identity)
                      let ticket = AuthenticationTicket(subject, BasicAuthenticationDefault.scheme)
                      return AuthenticateResult.success(ticket)
                  }
              }
              return AuthenticateResult.noResult()
          }
      
          /*
          重寫調(diào)戰(zhàn)處理邏輯:返回401狀態(tài)碼和Basic協(xié)議頭
          */
          protected override func handleChallenge(properties: ?AuthenticationProperties): Unit {
              this.context.response.addHeader("WWW-Authenticate", "Basic realm=\"${this.options.realm}\", charset=\"UTF-8\"")
              super.handleChallenge(properties)
          }
      }
      
      //定義資源所有者憑據(jù)驗(yàn)證
      public interface IResourceOwnerPasswordValidator {
          func validate(username: String, password: String): Bool
      }
      
      //實(shí)現(xiàn)資源所有者憑據(jù)驗(yàn)證
      public class ResourceOwnerPasswordValidator <: IResourceOwnerPasswordValidator {
          let users = HashMap<String, String>([("soulsoft", "soulsoft")])
      
          public func validate(username: String, password: String) {
              if (!users.contains(username)) {
                  return false
              }
              return users[username] == password
          }
      }
      

      啟動(dòng)web主機(jī)來運(yùn)行

      main (args: Array<String>) {
          let builder = WebHost.createBuilder(args)
      
          builder.services.addRouting()
          
          //注冊(cè)資源所有者驗(yàn)證器
          builder.services.addTransient<IResourceOwnerPasswordValidator, ResourceOwnerPasswordValidator>()
      
          //注冊(cè)身份認(rèn)證服務(wù)
          builder.services.addAuthentication(BasicAuthenticationDefault.scheme)
              //注冊(cè)basic認(rèn)證方案
              .addScheme<BasicAuthenticationOptions, BasicAuthenticationHandler>(BasicAuthenticationDefault.scheme)
          
          //注冊(cè)授權(quán)服務(wù)
          builder.services.addAuthorizationBuilder()
              //定義授權(quán)策略
              .addPolicy("base-policy"){ policy =>
                  //必須包含username
                  policy.requireClaim("username")
                  //基本要求,具體參考源碼
                  policy.requireAuthenticatedUser()
              }
          let host = builder.build()
      
          //啟用認(rèn)證中間件
          host.useAuthentication()
      
          host.useRouting()
      
          //啟用授權(quán)中間件
          host.useAuthorization()
      
          host.run()
      
          host.useEndpoints { endpoints =>
              endpoints.mapGet("logout") {
                  context => context.response.write("logout succeeded")
              }
              //啟用認(rèn)證策略
              .requireAuthorization("base-policy") 
          }
          return 0
      }
      
      • 由于授權(quán)中間件需要使用路由到的Endpoint,對(duì)終結(jié)點(diǎn)授權(quán),因此授權(quán)中間件必須放到useRouting后面
      • 注意:認(rèn)證是確定你是誰,無論成果與否都不影響流程,而授權(quán),需要驗(yàn)證你的身份,如果身份認(rèn)證不通過,那么將會(huì)發(fā)起challenge(挑戰(zhàn)),并返回401狀態(tài)碼。如果身份認(rèn)證通過,但是不滿足授權(quán)策略將會(huì)發(fā)起forbid(禁止)返回403狀態(tài)碼。你可以通過override來重寫挑戰(zhàn)和禁止的邏輯
      • web主機(jī)在分發(fā)請(qǐng)求的時(shí)候,創(chuàng)建了一個(gè)子容器放到HttpContextservices字段上,進(jìn)而實(shí)現(xiàn)請(qǐng)求scope級(jí)別的生命周期

      Jwt認(rèn)證方案

      main(args: Array<String>): Int64 {
      
          let builder = WebHost.createBuilder(args)
          //==============服務(wù)注冊(cè)==================
      	
      	//注冊(cè)路由
          builder.services.AddRouting()
          
          //注冊(cè)身份認(rèn)證方案
          builder.services.addAuthentication(JwtBearerAuthenticationDefaults.Scheme)
              //注冊(cè)basic認(rèn)證方案
              .addScheme<BasicAuthenticationOptions, BasicAuthenticationHandler>(BasicAuthenticationDefault.Scheme)
              //注冊(cè)jwtBearer認(rèn)證方案
              .addJwtBearer(JwtBearerAuthenticationDefaults.Scheme) { configureOptions =>
                  let securityKey = SymmetricSecurityKey(builder.configuration["authentication:securityKey"].getOrThrow().toArray())
                  configureOptions.tokenValidationParameters = TokenValidationParameters(securityKey)
              }
          
          //注冊(cè)授權(quán)服務(wù)
          builder.services.addAuthorizationBuilder()
              .addPolicy("default"){ policy =>
                  //必須包含username
                  policy.requireClaim("username")
                  //基本要求,具體參考源碼
                  policy.requireAuthenticatedUser()
          }
      
          //==============請(qǐng)求管道==================    
          let host = builder.build()
      
          //使用身份認(rèn)證
          host.useAuthentication()
      
          //動(dòng)態(tài)資源路由(負(fù)責(zé)路由,并放到HttpContext上)
          host.useRouting()
          
          //由于該中間件需要使用路由到的endpoint,因此必須放到useRouting后面
          host.useAuthorization()
          
          //動(dòng)態(tài)資源(負(fù)責(zé)注冊(cè)和執(zhí)行)
          host.useEndpoints { endpoints =>
      		
              //創(chuàng)建jwt token
              endpoints.mapGet("connect/token"){ context =>
                  let securityKey = SymmetricSecurityKey(host.configuration["authentication:securityKey"].getOrThrow().toArray())
                  let jwtHeader = JwtHeader(SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256))
                  let jwtPayload = JwtPayload([("sub", "1024"), ("username", "soulsoft")])
                  
                  let jwtTokenHander = JwtSecurityTokenHandler()
                  let accessToken = jwtTokenHander.writeToken(JwtSecurityToken(jwtHeader, jwtPayload))
                  context.response.write(accessToken)
              }
              
              //登入接口需要授權(quán)
              endpoints.mapGet("connect/logout") {
                  context => context.response.write("logout succeeded")
              }.requireAuthorization("default")       
          
          }
          host.run()
          return 0
      }
      
      posted on 2025-06-13 10:02  花間島  閱讀(74)  評(píng)論(0)    收藏  舉報(bào)

      主站蜘蛛池模板: 精品国产粉嫩一区二区三区| 久草网视频在线观看| 疯狂做受xxxx高潮欧美日本| 水蜜桃视频在线观看免费18| av高清无码 在线播放| 无码国产精品一区二区免费3p| 国产果冻豆传媒麻婆| 国产熟女一区二区三区四区| 国产精品国三级国产av| 亚洲熟妇色xxxxx亚洲| 精品一区二区三区蜜桃久| 亚洲av伦理一区二区| 精品在免费线中文字幕久久| 亚洲成亚洲成网| 国产成人8X人网站视频| 欧美一区内射最近更新| 久章草在线毛片视频播放| 少妇伦子伦情品无吗| 亚洲人成影院在线观看| 一区二区三区无码免费看| ww污污污网站在线看com| 亚洲乱码精品久久久久..| 好男人视频www在线观看| 久女女热精品视频在线观看| 老色99久久九九爱精品| 成 人色 网 站 欧美大片| 亚洲V天堂V手机在线| 天天躁夜夜躁狠狠喷水| 日韩精品一区二区三区视频| 国产超碰无码最新上传| 精品国产中文字幕在线看| 亚洲中文字幕国产精品| 色狠狠一区二区三区香蕉| 成人精品日韩专区在线观看| 无码免费大香伊蕉在人线国产| 日韩在线视频网| 日本中文一区二区三区亚洲| 国产91色在线精品三级| 亚洲国产色播AV在线| 国产精品99中文字幕| 熟女精品视频一区二区三区|