主頁 > .NET開發 > IdentityServer4原始碼決議_1_專案結構

IdentityServer4原始碼決議_1_專案結構

2020-09-16 04:01:03 .NET開發

目錄

  • IdentityServer4原始碼決議_1_專案結構
  • IdentityServer4原始碼決議_2_元資料介面
  • IdentityServer4原始碼決議_3_認證介面
  • IdentityServer4原始碼決議_4_令牌發放介面
  • IdentityServer4原始碼決議_5_查詢用戶資訊介面
  • [IdentityServer4原始碼決議_6_結束會話介面]
  • [IdentityServer4原始碼決議_7_查詢令牌資訊介面]
  • [IdentityServer4原始碼決議_8_撤銷令牌介面]

簡介

Security原始碼決議系列介紹了微軟提供的各種認證架構,其中OAuth2.0,OpenIdConnect屬于遠程認證架構,所謂遠程認證,是指token的頒發是由其他站點完成的,

IdentityServer4是基于OpenIdConnect協議的認證中心框架,可以幫助我們快速搭建微服務認證中心,

初學者可能看到生澀的概念比較頭疼,可以將OAuth, OpenIdConnect協議簡單理解成需求檔案,idsv4基于需求提供了一系列的api實作,

對于idsv還不太了解的可以看下面的資料,本系列主要學習梳理idsv4的原始碼,結合協議加深理解,

曉晨姐姐系列文章

https://www.cnblogs.com/stulzq/p/8119928.html

官方檔案

https://identityserver4.readthedocs.io/en/latest/

專案結構

專案地址如下

https://github.com/IdentityServer/IdentityServer4

克隆到本地,專案結構如圖

image

核心專案是IdentityServer4,其余的都是與微軟框架集成、以及處理持久化的專案,
專案結構如圖,Endpoints檔案夾就是介面檔案,我們先看下依賴注入、中間件的代碼,然后看下每個介面,
image

依賴注入

public static IIdentityServerBuilder AddIdentityServer(this IServiceCollection services)
{
    var builder = services.AddIdentityServerBuilder();

    builder
        .AddRequiredPlatformServices()
        .AddCookieAuthentication()
        .AddCoreServices()
        .AddDefaultEndpoints()
        .AddPluggableServices()
        .AddValidators()
        .AddResponseGenerators()
        .AddDefaultSecretParsers()
        .AddDefaultSecretValidators();

    // provide default in-memory implementation, not suitable for most production scenarios
    builder.AddInMemoryPersistedGrants();

    return builder;
}
  • AddRequiredPlatformServices - 注入平臺服務
    • IHttpContextAccessor:HttpContext訪問器
    • IdentityServerOptions:配置類
 public static IIdentityServerBuilder AddRequiredPlatformServices(this IIdentityServerBuilder builder)
{
    builder.Services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();            
    builder.Services.AddOptions();
    builder.Services.AddSingleton(
        resolver => resolver.GetRequiredService<IOptions<IdentityServerOptions>>().Value);
    builder.Services.AddHttpClient();

    return builder;
}
  • AddCookieAuthentication - 注入cookie服務
    • 注入名稱為idsrv的cookie認證架構
    • 注入IAuthenticationService的實作IdentityServerAuthenticationService
    • 注入IAuthenticationHandlerProvider的實作FederatedSignoutAuthenticationHandlerProvider
public static IIdentityServerBuilder AddCookieAuthentication(this IIdentityServerBuilder builder)
{
    builder.Services.AddAuthentication(IdentityServerConstants.DefaultCookieAuthenticationScheme)
        .AddCookie(IdentityServerConstants.DefaultCookieAuthenticationScheme)
        .AddCookie(IdentityServerConstants.ExternalCookieAuthenticationScheme);

    builder.Services.AddSingleton<IConfigureOptions<CookieAuthenticationOptions>, ConfigureInternalCookieOptions>();
    builder.Services.AddSingleton<IPostConfigureOptions<CookieAuthenticationOptions>, PostConfigureInternalCookieOptions>();
    builder.Services.AddTransientDecorator<IAuthenticationService, IdentityServerAuthenticationService>();
    builder.Services.AddTransientDecorator<IAuthenticationHandlerProvider, FederatedSignoutAuthenticationHandlerProvider>();

    return builder;
}
  • AddCoreServices - 注入核心服務
/// <summary>
/// Adds the core services.
/// </summary>
/// <param name="builder">The builder.</param>
/// <returns></returns>
public static IIdentityServerBuilder AddCoreServices(this IIdentityServerBuilder builder)
{
    builder.Services.AddTransient<SecretParser>();
    builder.Services.AddTransient<SecretValidator>();
    builder.Services.AddTransient<ScopeValidator>();
    builder.Services.AddTransient<ExtensionGrantValidator>();
    builder.Services.AddTransient<BearerTokenUsageValidator>();
    builder.Services.AddTransient<JwtRequestValidator>();

    // todo: remove in 3.0
#pragma warning disable CS0618 // Type or member is obsolete
    builder.Services.AddTransient<BackChannelHttpClient>();
#pragma warning restore CS0618 // Type or member is obsolete

    builder.Services.AddTransient<ReturnUrlParser>();
    builder.Services.AddTransient<IdentityServerTools>();

    builder.Services.AddTransient<IReturnUrlParser, OidcReturnUrlParser>();
    builder.Services.AddScoped<IUserSession, DefaultUserSession>();
    builder.Services.AddTransient(typeof(MessageCookie<>));

    builder.Services.AddCors();
    builder.Services.AddTransientDecorator<ICorsPolicyProvider, CorsPolicyProvider>();

    return builder;
}
  • AddDefaultEndpoints - 注入介面
    • AuthorizeCallbackEndpoint:認證回呼介面
    • AuthorizeEndpoint:認證介面
    • CheckSessionEndpoint:檢查會話介面
    • DeviceAuthorizationEndpoint:設備認證介面
    • DiscoveryEndpoint:元資料鍵介面
    • DiscoveryEndpoint:元資料介面
    • EndSessionCallbackEndpoint:結束會話回呼介面
    • EndSessionEndpoint:結束會話介面
    • IntrospectionEndpoint:查詢令牌資訊介面
    • TokenRevocationEndpoint:撤銷令牌介面
    • TokenEndpoint:發放令牌介面
    • UserInfoEndpoint:查詢用戶資訊介面

注入所有默認介面,包括介面名稱和地址,請求進來之后,路由類EndPointRouter通過路由來尋找匹配的處理器,

 public static IIdentityServerBuilder AddDefaultEndpoints(this IIdentityServerBuilder builder)
{
    builder.Services.AddTransient<IEndpointRouter, EndpointRouter>();

    builder.AddEndpoint<AuthorizeCallbackEndpoint>(EndpointNames.Authorize, ProtocolRoutePaths.AuthorizeCallback.EnsureLeadingSlash());
    builder.AddEndpoint<AuthorizeEndpoint>(EndpointNames.Authorize, ProtocolRoutePaths.Authorize.EnsureLeadingSlash());
    builder.AddEndpoint<CheckSessionEndpoint>(EndpointNames.CheckSession, ProtocolRoutePaths.CheckSession.EnsureLeadingSlash());
    builder.AddEndpoint<DeviceAuthorizationEndpoint>(EndpointNames.DeviceAuthorization, ProtocolRoutePaths.DeviceAuthorization.EnsureLeadingSlash());
    builder.AddEndpoint<DiscoveryKeyEndpoint>(EndpointNames.Discovery, ProtocolRoutePaths.DiscoveryWebKeys.EnsureLeadingSlash());
    builder.AddEndpoint<DiscoveryEndpoint>(EndpointNames.Discovery, ProtocolRoutePaths.DiscoveryConfiguration.EnsureLeadingSlash());
    builder.AddEndpoint<EndSessionCallbackEndpoint>(EndpointNames.EndSession, ProtocolRoutePaths.EndSessionCallback.EnsureLeadingSlash());
    builder.AddEndpoint<EndSessionEndpoint>(EndpointNames.EndSession, ProtocolRoutePaths.EndSession.EnsureLeadingSlash());
    builder.AddEndpoint<IntrospectionEndpoint>(EndpointNames.Introspection, ProtocolRoutePaths.Introspection.EnsureLeadingSlash());
    builder.AddEndpoint<TokenRevocationEndpoint>(EndpointNames.Revocation, ProtocolRoutePaths.Revocation.EnsureLeadingSlash());
    builder.AddEndpoint<TokenEndpoint>(EndpointNames.Token, ProtocolRoutePaths.Token.EnsureLeadingSlash());
    builder.AddEndpoint<UserInfoEndpoint>(EndpointNames.UserInfo, ProtocolRoutePaths.UserInfo.EnsureLeadingSlash());

    return builder;
}
  • AddPluggableServices - 注入可插拔服務
public static IIdentityServerBuilder AddPluggableServices(this IIdentityServerBuilder builder)
{
    builder.Services.TryAddTransient<IPersistedGrantService, DefaultPersistedGrantService>();
    builder.Services.TryAddTransient<IKeyMaterialService, DefaultKeyMaterialService>();
    builder.Services.TryAddTransient<ITokenService, DefaultTokenService>();
    builder.Services.TryAddTransient<ITokenCreationService, DefaultTokenCreationService>();
    builder.Services.TryAddTransient<IClaimsService, DefaultClaimsService>();
    builder.Services.TryAddTransient<IRefreshTokenService, DefaultRefreshTokenService>();
    builder.Services.TryAddTransient<IDeviceFlowCodeService, DefaultDeviceFlowCodeService>();
    builder.Services.TryAddTransient<IConsentService, DefaultConsentService>();
    builder.Services.TryAddTransient<ICorsPolicyService, DefaultCorsPolicyService>();
    builder.Services.TryAddTransient<IProfileService, DefaultProfileService>();
    builder.Services.TryAddTransient<IConsentMessageStore, ConsentMessageStore>();
    builder.Services.TryAddTransient<IMessageStore<LogoutMessage>, ProtectedDataMessageStore<LogoutMessage>>();
    builder.Services.TryAddTransient<IMessageStore<EndSession>, ProtectedDataMessageStore<EndSession>>();
    builder.Services.TryAddTransient<IMessageStore<ErrorMessage>, ProtectedDataMessageStore<ErrorMessage>>();
    builder.Services.TryAddTransient<IIdentityServerInteractionService, DefaultIdentityServerInteractionService>();
    builder.Services.TryAddTransient<IDeviceFlowInteractionService, DefaultDeviceFlowInteractionService>();
    builder.Services.TryAddTransient<IAuthorizationCodeStore, DefaultAuthorizationCodeStore>();
    builder.Services.TryAddTransient<IRefreshTokenStore, DefaultRefreshTokenStore>();
    builder.Services.TryAddTransient<IReferenceTokenStore, DefaultReferenceTokenStore>();
    builder.Services.TryAddTransient<IUserConsentStore, DefaultUserConsentStore>();
    builder.Services.TryAddTransient<IHandleGenerationService, DefaultHandleGenerationService>();
    builder.Services.TryAddTransient<IPersistentGrantSerializer, PersistentGrantSerializer>();
    builder.Services.TryAddTransient<IEventService, DefaultEventService>();
    builder.Services.TryAddTransient<IEventSink, DefaultEventSink>();
    builder.Services.TryAddTransient<IUserCodeService, DefaultUserCodeService>();
    builder.Services.TryAddTransient<IUserCodeGenerator, NumericUserCodeGenerator>();
    builder.Services.TryAddTransient<IBackChannelLogoutService, DefaultBackChannelLogoutService>();

    builder.AddJwtRequestUriHttpClient();
    builder.AddBackChannelLogoutHttpClient();
    //builder.Services.AddHttpClient<BackChannelLogoutHttpClient>();
    //builder.Services.AddHttpClient<JwtRequestUriHttpClient>();

    builder.Services.AddTransient<IClientSecretValidator, ClientSecretValidator>();
    builder.Services.AddTransient<IApiSecretValidator, ApiSecretValidator>();

    builder.Services.TryAddTransient<IDeviceFlowThrottlingService, DistributedDeviceFlowThrottlingService>();
    builder.Services.AddDistributedMemoryCache();

    return builder;
}
  • AddValidators - 注入校驗類
public static IIdentityServerBuilder AddValidators(this IIdentityServerBuilder builder)
{
    // core
    builder.Services.TryAddTransient<IEndSessionRequestValidator, EndSessionRequestValidator>();
    builder.Services.TryAddTransient<ITokenRevocationRequestValidator, TokenRevocationRequestValidator>();
    builder.Services.TryAddTransient<IAuthorizeRequestValidator, AuthorizeRequestValidator>();
    builder.Services.TryAddTransient<ITokenRequestValidator, TokenRequestValidator>();
    builder.Services.TryAddTransient<IRedirectUriValidator, StrictRedirectUriValidator>();
    builder.Services.TryAddTransient<ITokenValidator, TokenValidator>();
    builder.Services.TryAddTransient<IIntrospectionRequestValidator, IntrospectionRequestValidator>();
    builder.Services.TryAddTransient<IResourceOwnerPasswordValidator, NotSupportedResourceOwnerPasswordValidator>();
    builder.Services.TryAddTransient<ICustomTokenRequestValidator, DefaultCustomTokenRequestValidator>();
    builder.Services.TryAddTransient<IUserInfoRequestValidator, UserInfoRequestValidator>();
    builder.Services.TryAddTransient<IClientConfigurationValidator, DefaultClientConfigurationValidator>();
    builder.Services.TryAddTransient<IDeviceAuthorizationRequestValidator, DeviceAuthorizationRequestValidator>();
    builder.Services.TryAddTransient<IDeviceCodeValidator, DeviceCodeValidator>();

    // optional
    builder.Services.TryAddTransient<ICustomTokenValidator, DefaultCustomTokenValidator>();
    builder.Services.TryAddTransient<ICustomAuthorizeRequestValidator, DefaultCustomAuthorizeRequestValidator>();
    
    return builder;
}
  • AddResponseGenerators - 注入回應生成類
public static IIdentityServerBuilder AddResponseGenerators(this IIdentityServerBuilder builder)
{
    builder.Services.TryAddTransient<ITokenResponseGenerator, TokenResponseGenerator>();
    builder.Services.TryAddTransient<IUserInfoResponseGenerator, UserInfoResponseGenerator>();
    builder.Services.TryAddTransient<IIntrospectionResponseGenerator, IntrospectionResponseGenerator>();
    builder.Services.TryAddTransient<IAuthorizeInteractionResponseGenerator, AuthorizeInteractionResponseGenerator>();
    builder.Services.TryAddTransient<IAuthorizeResponseGenerator, AuthorizeResponseGenerator>();
    builder.Services.TryAddTransient<IDiscoveryResponseGenerator, DiscoveryResponseGenerator>();
    builder.Services.TryAddTransient<ITokenRevocationResponseGenerator, TokenRevocationResponseGenerator>();
    builder.Services.TryAddTransient<IDeviceAuthorizationResponseGenerator, DeviceAuthorizationResponseGenerator>();

    return builder;
}
  • AddDefaultSecretParsers & AddDefaultSecretValidators
/// <summary>
/// Adds the default secret parsers.
/// </summary>
/// <param name="builder">The builder.</param>
/// <returns></returns>
public static IIdentityServerBuilder AddDefaultSecretParsers(this IIdentityServerBuilder builder)
{
    builder.Services.AddTransient<ISecretParser, BasicAuthenticationSecretParser>();
    builder.Services.AddTransient<ISecretParser, PostBodySecretParser>();

    return builder;
}

/// <summary>
/// Adds the default secret validators.
/// </summary>
/// <param name="builder">The builder.</param>
/// <returns></returns>
public static IIdentityServerBuilder AddDefaultSecretValidators(this IIdentityServerBuilder builder)
{
    builder.Services.AddTransient<ISecretValidator, HashedSharedSecretValidator>();

    return builder;
}

IdentityServerOptions - 配置類

 /// <summary>
/// The IdentityServerOptions class is the top level container for all configuration settings of IdentityServer.
/// </summary>
public class IdentityServerOptions
{
    /// <summary>
    /// Gets or sets the unique name of this server instance, e.g. https://myissuer.com.
    /// If not set, the issuer name is inferred from the request
    /// </summary>
    /// <value>
    /// Unique name of this server instance, e.g. https://myissuer.com
    /// </value>
    public string IssuerUri { get; set; }

    /// <summary>
    /// Gets or sets the origin of this server instance, e.g. https://myorigin.com.
    /// If not set, the origin name is inferred from the request
    /// Note: Do not set a URL or include a path.
    /// </summary>
    /// <value>
    /// Origin of this server instance, e.g. https://myorigin.com
    /// </value>
    public string PublicOrigin { get; set; }

    /// <summary>
    /// Gets or sets the value for the JWT typ header for access tokens.
    /// </summary>
    /// <value>
    /// The JWT typ value.
    /// </value>
    public string AccessTokenJwtType { get; set; } = "at+jwt";

    /// <summary>
    /// Emits an aud claim with the format issuer/resources. That's needed for some older access token validation plumbing. Defaults to false.
    /// </summary>
    public bool EmitLegacyResourceAudienceClaim { get; set; } = false;

    /// <summary>
    /// Gets or sets the endpoint configuration.
    /// </summary>
    /// <value>
    /// The endpoints configuration.
    /// </value>
    public EndpointsOptions Endpoints { get; set; } = new EndpointsOptions();

    /// <summary>
    /// Gets or sets the discovery endpoint configuration.
    /// </summary>
    /// <value>
    /// The discovery endpoint configuration.
    /// </value>
    public DiscoveryOptions Discovery { get; set; } = new DiscoveryOptions();

    /// <summary>
    /// Gets or sets the authentication options.
    /// </summary>
    /// <value>
    /// The authentication options.
    /// </value>
    public AuthenticationOptions Authentication { get; set; } = new AuthenticationOptions();

    /// <summary>
    /// Gets or sets the events options.
    /// </summary>
    /// <value>
    /// The events options.
    /// </value>
    public EventsOptions Events { get; set; } = new EventsOptions();

    /// <summary>
    /// Gets or sets the max input length restrictions.
    /// </summary>
    /// <value>
    /// The length restrictions.
    /// </value>
    public InputLengthRestrictions InputLengthRestrictions { get; set; } = new InputLengthRestrictions();

    /// <summary>
    /// Gets or sets the options for the user interaction.
    /// </summary>
    /// <value>
    /// The user interaction options.
    /// </value>
    public UserInteractionOptions UserInteraction { get; set; } = new UserInteractionOptions();

    /// <summary>
    /// Gets or sets the caching options.
    /// </summary>
    /// <value>
    /// The caching options.
    /// </value>
    public CachingOptions Caching { get; set; } = new CachingOptions();

    /// <summary>
    /// Gets or sets the cors options.
    /// </summary>
    /// <value>
    /// The cors options.
    /// </value>
    public CorsOptions Cors { get; set; } = new CorsOptions();

    /// <summary>
    /// Gets or sets the Content Security Policy options.
    /// </summary>
    public CspOptions Csp { get; set; } = new CspOptions();

    /// <summary>
    /// Gets or sets the validation options.
    /// </summary>
    public ValidationOptions Validation { get; set; } = new ValidationOptions();

    /// <summary>
    /// Gets or sets the device flow options.
    /// </summary>
    public DeviceFlowOptions DeviceFlow { get; set; } = new DeviceFlowOptions();

    /// <summary>
    /// Gets or sets the mutual TLS options.
    /// </summary>
    public MutualTlsOptions MutualTls { get; set; } = new MutualTlsOptions();
}

UserIdentityServer - 中間件邏輯

  • 執行校驗
  • BaseUrlMiddleware中間件:設定BaseUrl
  • 配置CORS跨域:CorsPolicyProvider根據client資訊生成動態策略
  • IdentityServerMiddlewareOptions默認呼叫了UseAuthentication,所以如果使用IdentityServer不用重復注冊Authentication中間件
  • 使用MutualTlsTokenEndpointMiddleware中間件:要求客戶端、服務端都使用https,默認不開啟
  • 使用IdentityServerMiddleware中間件:IEndpointRouter根據請求尋找匹配的IEndpointHandler,如果找到的話則由EndPointHandler處理請求,
public static IApplicationBuilder UseIdentityServer(this IApplicationBuilder app, IdentityServerMiddlewareOptions options = null)
{
    app.Validate();

    app.UseMiddleware<BaseUrlMiddleware>();

    app.ConfigureCors();

    // it seems ok if we have UseAuthentication more than once in the pipeline --
    // this will just re-run the various callback handlers and the default authN 
    // handler, which just re-assigns the user on the context. claims transformation
    // will run twice, since that's not cached (whereas the authN handler result is)
    // related: https://github.com/aspnet/Security/issues/1399
    if (options == null) options = new IdentityServerMiddlewareOptions();
    options.AuthenticationMiddleware(app);

    app.UseMiddleware<MutualTlsTokenEndpointMiddleware>();
    app.UseMiddleware<IdentityServerMiddleware>();

    return app;
}

核心中間件IdentityServerMiddleware的代碼,邏輯比較清晰

  • IEndpointRouter路由類旬齋匹配介面
  • 匹配介面處理請求回傳結果IEndpointResult
  • IEndpointResult執行結果,寫入背景關系,回傳報文
 public async Task Invoke(HttpContext context, IEndpointRouter router, IUserSession session, IEventService events)
{
    // this will check the authentication session and from it emit the check session
    // cookie needed from JS-based signout clients.
    await session.EnsureSessionIdCookieAsync();

    try
    {
        var endpoint = router.Find(context);
        if (endpoint != null)
        {
            _logger.LogInformation("Invoking IdentityServer endpoint: {endpointType} for {url}", endpoint.GetType().FullName, context.Request.Path.ToString());

            var result = await endpoint.ProcessAsync(context);

            if (result != null)
            {
                _logger.LogTrace("Invoking result: {type}", result.GetType().FullName);
                await result.ExecuteAsync(context);
            }

            return;
        }
    }
    catch (Exception ex)
    {
        await events.RaiseAsync(new UnhandledExceptionEvent(ex));
        _logger.LogCritical(ex, "Unhandled exception: {exception}", ex.Message);
        throw;
    }

    await _next(context);
}

看一下路由類的處理邏輯
之前AddDefaultEndpoints注入了所有默認介面,路由類可以通過依賴注入拿到所有介面資訊,將請求地址與介面地址對比得到匹配的介面,然后從容器拿到對應的介面處理器,

public EndpointRouter(IEnumerable<Endpoint> endpoints, IdentityServerOptions options, ILogger<EndpointRouter> logger)
{
    _endpoints = endpoints;
    _options = options;
    _logger = logger;
}

public IEndpointHandler Find(HttpContext context)
{
    if (context == null) throw new ArgumentNullException(nameof(context));

    foreach(var endpoint in _endpoints)
    {
        var path = endpoint.Path;
        if (context.Request.Path.Equals(path, StringComparison.OrdinalIgnoreCase))
        {
            var endpointName = endpoint.Name;
            _logger.LogDebug("Request path {path} matched to endpoint type {endpoint}", context.Request.Path, endpointName);

            return GetEndpointHandler(endpoint, context);
        }
    }

    _logger.LogTrace("No endpoint entry found for request path: {path}", context.Request.Path);

    return null;
}

 private IEndpointHandler GetEndpointHandler(Endpoint endpoint, HttpContext context)
{
    if (_options.Endpoints.IsEndpointEnabled(endpoint))
    {
        var handler = context.RequestServices.GetService(endpoint.Handler) as IEndpointHandler;
        if (handler != null)
        {
            _logger.LogDebug("Endpoint enabled: {endpoint}, successfully created handler: {endpointHandler}", endpoint.Name, endpoint.Handler.FullName);
            return handler;
        }
        else
        {
            _logger.LogDebug("Endpoint enabled: {endpoint}, failed to create handler: {endpointHandler}", endpoint.Name, endpoint.Handler.FullName);
        }
    }
    else
    {
        _logger.LogWarning("Endpoint disabled: {endpoint}", endpoint.Name);
    }

    return null;
}

總結

主干流程大致如圖
image

idsv的代碼量還是比較大的,有很多的類,但是代碼還是要寫的挺規范清晰,梳理下來脈絡還是很明了的,

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/52868.html

標籤:.NET Core

上一篇:AspNetCore3.1_Secutiry原始碼決議_8_Authorization_授權框架

下一篇:IdentityServer4原始碼決議_2_元資料介面

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more