主頁 > .NET開發 > IdentityServer4系列 | 混合模式

IdentityServer4系列 | 混合模式

2020-12-16 15:00:49 .NET開發

一、前言

在上一篇關于授權碼模式中, 已經介紹了關于授權碼的基本內容,認識到這是一個擁有更為安全的機制,但這個仍然存在局限,雖然在文中我們說到通過后端的方式去獲取token,這種由web服務器和授權服務器直接通信,不需要經過用戶的瀏覽器或者其他的地方,但是在這種模式中,授權碼仍然是通過前端通道進行傳遞的,而且在訪問資源的中,也會將訪問令牌暴露給外界,就仍存在安全隱患,

快速回顧一下之前初識基礎知識點中提到的,IdentityServer4OpenID Connect + OAuth2.0 相結合的認證框架,用戶身份認證和API的授權訪問,兩個結合一塊,實作了認證和授權的結合,

在幾篇關于授權模式篇章中,其中我們也使用了關于OpenID Connect 的簡化流程,在簡化流程中,所有令牌(身份令牌、訪問令牌)都通過瀏覽器傳輸,這對于身份令牌(IdentityToken)來說是沒有問題的,但是如果是訪問令牌(AccessToken)直接通過瀏覽器傳輸,就增加了一定的安全問題,因為訪問令牌比身份令牌更敏感,在非必須的情況下,我們不希望將它們暴露給外界,

所以我們就會考慮增加安全性,在OpenID Connect 包含一個名為“Hybrid(混合)”的流程,它為我們提供了兩全其美的優勢,身份令牌通過瀏覽器傳輸,因此客戶端可以在進行任何更多作業之前對其進行驗證,如果驗證成功,客戶端會通過令牌服務的以獲取訪問令牌,

二、初識

在認識混合模式(Hybrid Flow)時候,可以發現這里跟上一篇的授權碼模式有很多相似的地方,具體可以查看授權碼模式

查看使用OpenIDConnect時的安全性和隱私注意事項相關資料可以發現,

授權碼模式混合模式的流程步驟分別如下:

Authorization Code Flow Steps

The Authorization Code Flow goes through the following steps.

  1. Client prepares an Authentication Request containing the desired request parameters.
  2. Client sends the request to the Authorization Server.
  3. Authorization Server Authenticates the End-User.
  4. Authorization Server obtains End-User Consent/Authorization.
  5. Authorization Server sends the End-User back to the Client with an Authorization Code.
  6. Client requests a response using the Authorization Code at the Token Endpoint.
  7. Client receives a response that contains an ID Token and Access Token in the response body.
  8. Client validates the ID token and retrieves the End-User's Subject Identifier.

Hybrid Flow Steps

The Hybrid Flow follows the following steps:

  1. Client prepares an Authentication Request containing the desired request parameters.
  2. Client sends the request to the Authorization Server.
  3. Authorization Server Authenticates the End-User.
  4. Authorization Server obtains End-User Consent/Authorization.
  5. Authorization Server sends the End-User back to the Client with an Authorization Code and, depending on the Response Type, one or more additional parameters.
  6. Client requests a response using the Authorization Code at the Token Endpoint.
  7. Client receives a response that contains an ID Token and Access Token in the response body.
  8. Client validates the ID Token and retrieves the End-User's Subject Identifier.

由以上對比發現,codehybrid一樣都有8個步驟,大部分步驟也是相同的,最主要的區別在于第5步,

在授權碼模式中,成功回應身份驗證

 HTTP/1.1 302 Found
  Location: https://client.example.org/cb?
    code=SplxlOBeZQQYbYS6WxSbIA
    &state=af0ifjsldkj

在混合模式中,成功回應身份驗證:

HTTP/1.1 302 Found
  Location: https://client.example.org/cb#
    code=SplxlOBeZQQYbYS6WxSbIA
    &id_token=eyJ0 ... NiJ9.eyJ1c ... I6IjIifX0.DeWt4Qu ... ZXso
    &state=af0ifjsldkj

其中多了一個id_token

在使用這些模式的時候,成功的身份驗證回應,存在指定的差異,這些授權端點的結果以不同的的依據回傳,其中code是一定會回傳的,access_token和id_token的回傳依據 response_type 引數決定,

混合模式根據response_type的不同,authorization endpoint回傳可以分為三種情況,

  1. response_type = code + id_token ,即包含Access Token和ID Token
  2. response_type = code + token ,即包含Authorization Code和Access Token
  3. response_type = code + id_token + token,即包含Authorization Code、identity Token和Access Token

三、實踐

接著我們進行一些簡單的實踐,因為有了前面授權碼模式代碼的經驗,撰寫混合模式也是很簡單的,

(這里重復之前的代碼,防止被爬抓后內容的缺失不完整)

在示例實踐中,我們將創建一個授權訪問服務,定義一個MVC客戶端,MVC客戶端通過IdentityServer上請求訪問令牌,并使用它來訪問API,

3.1 搭建 Authorization Server 服務

搭建認證授權服務

3.1.1 安裝Nuget包

IdentityServer4 程式包

3.1.2 配置內容

建立配置內容檔案Config.cs

public static class Config
{
    public static IEnumerable<IdentityResource> IdentityResources =>
        new IdentityResource[]
    {
        new IdentityResources.OpenId(),
        new IdentityResources.Profile(),
    };

    public static IEnumerable<ApiScope> ApiScopes =>
        new ApiScope[]
    {
        new ApiScope("hybrid_scope1")
    };

    public static IEnumerable<ApiResource> ApiResources =>
        new ApiResource[]
    {
        new ApiResource("api1","api1")
        {
            Scopes={ "hybrid_scope1" },
            UserClaims={JwtClaimTypes.Role},  //添加Cliam 角色型別
            ApiSecrets={new Secret("apipwd".Sha256())}
        }
    };

    public static IEnumerable<Client> Clients =>
        new Client[]
    {
        new Client
        {
            ClientId = "hybrid_client",
            ClientName = "hybrid Auth",
			ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },
            AllowedGrantTypes = GrantTypes.Hybrid,

            RedirectUris ={
                "http://localhost:5002/signin-oidc", //跳轉登錄到的客戶端的地址
            },
            // RedirectUris = {"http://localhost:5002/auth.html" }, //跳轉登出到的客戶端的地址
            PostLogoutRedirectUris ={
                "http://localhost:5002/signout-callback-oidc",
            },
            ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },

            AllowedScopes = {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                "hybrid_scope1"
            },
            //允許將token通過瀏覽器傳遞
            AllowAccessTokensViaBrowser=true,
            // 是否需要同意授權 (默認是false)
            RequireConsent=true
        }
    };
}

RedirectUris : 登錄成功回呼處理的客戶端地址,處理回呼回傳的資料,可以有多個,

PostLogoutRedirectUris :跳轉登出到的客戶端的地址,

這兩個都是配置的客戶端的地址,且是identityserver4組件里面封裝好的地址,作用分別是登錄,注銷的回呼

因為是混合授權的方式,所以我們通過代碼的方式來創建幾個測驗用戶,

新建測驗用戶檔案TestUsers.cs

    public class TestUsers
    {
        public static List<TestUser> Users
        {
            get
            {
                var address = new
                {
                    street_address = "One Hacker Way",
                    locality = "Heidelberg",
                    postal_code = 69118,
                    country = "Germany"
                };

                return new List<TestUser>
                {
                    new TestUser
                    {
                        SubjectId = "1",
                        Username = "i3yuan",
                        Password = "123456",
                        Claims =
                        {
                            new Claim(JwtClaimTypes.Name, "i3yuan Smith"),
                            new Claim(JwtClaimTypes.GivenName, "i3yuan"),
                            new Claim(JwtClaimTypes.FamilyName, "Smith"),
                            new Claim(JwtClaimTypes.Email, "[email protected]"),
                            new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
                            new Claim(JwtClaimTypes.WebSite, "http://i3yuan.top"),
                            new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(address), IdentityServerConstants.ClaimValueTypes.Json)
                        }
                    }
                };
            }
        }
    }

回傳一個TestUser的集合,

通過以上添加好配置和測驗用戶后,我們需要將用戶注冊到IdentityServer4服務中,接下來繼續介紹,

3.1.3 注冊服務

在startup.cs中ConfigureServices方法添加如下代碼:

        public void ConfigureServices(IServiceCollection services)
        {
            var builder = services.AddIdentityServer()
               .AddTestUsers(TestUsers.Users); //添加測驗用戶

            // in-memory, code config
            builder.AddInMemoryIdentityResources(Config.IdentityResources);
            builder.AddInMemoryApiScopes(Config.ApiScopes);
            builder.AddInMemoryApiResources(Config.ApiResources);
            builder.AddInMemoryClients(Config.Clients);

            // not recommended for production - you need to store your key material somewhere secure
            builder.AddDeveloperSigningCredential();
            services.ConfigureNonBreakingSameSiteCookies();
        }

3.1.4 配置管道

在startup.cs中Configure方法添加如下代碼:

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseStaticFiles();
            app.UseRouting();
            app.UseCookiePolicy();
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseIdentityServer();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapDefaultControllerRoute();
            }); 
        }

以上內容是快速搭建簡易IdentityServer專案服務的方式,

這搭建 Authorization Server 服務跟上一篇授權碼模式有何不同之處呢?

  1. 在Config中配置客戶端(client)中定義了一個AllowedGrantTypes的屬性,這個屬性決定了Client可以被哪種模式被訪問,GrantTypes.Hybrid混合模式,所以在本文中我們需要添加一個Client用于支持授權碼模式(Hybrid),

3.2 搭建API資源

實作對API資源進行保護

3.2.1 快速搭建一個API專案

3.2.2 安裝Nuget包

IdentityServer4.AccessTokenValidation 包

3.2.3 注冊服務

在startup.cs中ConfigureServices方法添加如下代碼:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        services.AddAuthentication("Bearer")
          .AddIdentityServerAuthentication(options =>
          {
              options.Authority = "http://localhost:5001";
              options.RequireHttpsMetadata = https://www.cnblogs.com/i3yuan/p/false;
              options.ApiName ="api1";
              options.ApiSecret = "apipwd"; //對應ApiResources中的密鑰
          });
    }

AddAuthentication把Bearer配置成默認模式,將身份認證服務添加到DI中,

AddIdentityServerAuthentication把IdentityServer的access token添加到DI中,供身份認證服務使用,

3.2.4 配置管道

在startup.cs中Configure方法添加如下代碼:

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }    
            app.UseRouting();
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapDefaultControllerRoute();
            });
        }

UseAuthentication將身份驗證中間件添加到管道中;

UseAuthorization 將啟動授權中間件添加到管道中,以便在每次呼叫主機時執行身份驗證授權功能,

3.2.5 添加API資源介面

[Route("api/[Controller]")]
[ApiController]
public class IdentityController:ControllerBase
{
    [HttpGet("getUserClaims")]
    [Authorize]
    public IActionResult GetUserClaims()
    {
        return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
    }
}

在IdentityController 控制器中添加 [Authorize] , 在進行請求資源的時候,需進行認證授權通過后,才能進行訪問,

3.3 搭建MVC 客戶端

實作對客戶端認證授權訪問資源

3.3.1 快速搭建一個MVC專案

3.3.2 安裝Nuget包

IdentityServer4.AccessTokenValidation 包

3.3.3 注冊服務

要將對 OpenID Connect 身份認證的支持添加到MVC應用程式中,

在startup.cs中ConfigureServices方法添加如下代碼:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddAuthorization();

        services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
               .AddCookie("Cookies")  //使用Cookie作為驗證用戶的首選方式
              .AddOpenIdConnect("oidc", options =>
              {
                  options.Authority = "http://localhost:5001";  //授權服務器地址
                  options.RequireHttpsMetadata = https://www.cnblogs.com/i3yuan/p/false;  //暫時不用https
                  options.ClientId ="hybrid_client";
                  options.ClientSecret = "511536EF-F270-4058-80CA-1C89C192F69A";
                  options.ResponseType = "code id_token"; //代表
                  options.Scope.Add("hybrid_scope1"); //添加授權資源
                  options.SaveTokens = true; //表示把獲取的Token存到Cookie中
                  options.GetClaimsFromUserInfoEndpoint = true;
              });
         services.ConfigureNonBreakingSameSiteCookies();
    }
  1. AddAuthentication注入添加認證授權,當需要用戶登錄時,使用 cookie 來本地登錄用戶(通過“Cookies”作為DefaultScheme),并將 DefaultChallengeScheme 設定為“oidc”,
  2. 使用 AddCookie 添加可以處理 cookie 的處理程式,
  3. AddOpenIdConnect用于配置執行 OpenID Connect 協議的處理程式和相關引數,Authority表明之前搭建的 IdentityServer 授權服務地址,然后我們通過ClientIdClientSecret,識別這個客戶端, SaveTokens用于保存從IdentityServer獲取的token至cookie,ture標識ASP.NETCore將會自動存盤身份認證session的access和refresh token,
  4. 我們在配置ResponseType時需要使用Hybrid定義的三種情況之一,具體代碼如上所述,

3.3.4 配置管道

然后要確保認證服務執行對每個請求的驗證,加入UseAuthenticationUseAuthorizationConfigure中,在startup.cs中Configure方法添加如下代碼:

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }
            app.UseStaticFiles();
            app.UseRouting();
            app.UseCookiePolicy();
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }

UseAuthentication將身份驗證中間件添加到管道中;

UseAuthorization 將啟動授權中間件添加到管道中,以便在每次呼叫主機時執行身份驗證授權功能,

3.3.5 添加授權

在HomeController控制器并添加[Authorize]特性到其中一個方法,在進行請求的時候,需進行認證授權通過后,才能進行訪問,

        [Authorize]
        public IActionResult Privacy()
        {
            ViewData["Message"] = "Secure page.";
            return View();
        }

還要修改主視圖以顯示用戶的Claim以及cookie屬性,

@using Microsoft.AspNetCore.Authentication

<h2>Claims</h2>

<dl>
    @foreach (var claim in User.Claims)
    {
        <dt>@claim.Type</dt>
        <dd>@claim.Value</dd>
    }
</dl>

<h2>Properties</h2>

<dl>
    @foreach (var prop in (await Context.AuthenticateAsync()).Properties.Items)
    {
        <dt>@prop.Key</dt>
        <dd>@prop.Value</dd>
    }
</dl>

訪問 Privacy 頁面,跳轉到認證服務地址,進行賬號密碼登錄,Logout 用于用戶的注銷操作,

3.3.6 添加資源訪問

HomeController控制器添加對API資源訪問的介面方法,在進行請求的時候,訪問API受保護資源,

        /// <summary>
        /// 測驗請求API資源(api1)
        /// </summary>
        /// <returns></returns>
        public async Task<IActionResult> getApi()
        {
            var client = new HttpClient();
            var accessToken = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken);
            if (string.IsNullOrEmpty(accessToken))
            {
                return Json(new { msg = "accesstoken 獲取失敗" });
            }
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            var httpResponse = await client.GetAsync("http://localhost:5003/api/identity/GetUserClaims"); 
            var result = await httpResponse.Content.ReadAsStringAsync();
            if (!httpResponse.IsSuccessStatusCode)
            {
                return Json(new { msg = "請求 api1 失敗,", error = result });
            }
            return Json(new
            {
                msg = "成功",
                data = https://www.cnblogs.com/i3yuan/p/JsonConvert.DeserializeObject(result)
            });
        }

測驗這里通過獲取accessToken之后,設定client請求頭的認證,訪問API資源受保護的地址,獲取資源,

3.4 效果

我們通過對比授權碼模式與混合模式 可以發現,在大部分步驟是相同的,但也存在一些差異,

在整個程序中,我們使用抓取請求,可以看到在Authorization Endpoint中兩者的區別如下:

授權碼模式:

混合模式:

在Authorization EndPoint回傳的Id_Token和Token EndPoint回傳的id_Token中,可以看到兩次值是可能不相同的,但是其中包含的用戶資訊都是一樣的,

在使用Hybrid時我們看到授權終結點回傳的Id Token中包含at_hash(Access Token的哈希值)和s_hash(State的哈希值),規范中定義了以下的一些檢驗規則,

  1. 兩個id_token中的 iss 和 sub 必須相同,
  2. 如果任何一個 id token 中包含關于終端用戶的宣告,兩個令牌中提供的值必須相同,
  3. 關于驗證事件的宣告必須都提供,
  4. at_hash 和 s_hash 宣告可能會從 token 端點回傳的令牌中忽略,即使從 authorize 端點回傳的令牌中已經宣告,

四、問題

4.1 設定RequirePkce

在指定基于授權碼的令牌是否需要驗證密鑰,默認為true,

解決方法:

修改Config中的RequirePkce為false即可,這樣服務端便不在需要客戶端提供code challeng,

 RequirePkce = false,//v4.x需要配置這個

4.2 設定ResponseType

在上文中提到的MVC客戶端中配置ResponseType時可以使用Hybrid定義的三種情況,

而當設定為"code token", "code id_token token"中的一種,即只要包含token,都會報如下錯誤:

解決方法:

授權服務端中的Config中增加允許將token通過瀏覽器傳遞

AllowAccessTokensViaBrowser = true,

五、總結

  1. 由于令牌都通過瀏覽器傳輸,為了提高更好的安全性,我們不想暴露訪問令牌, OpenID Connect包含一個名為“Hybrid(混合)”的流程,它可以讓身份令牌(id_token)通過前端瀏覽器通道傳輸,因此客戶端可以在做更多的作業之前驗證它, 如果驗證成功,客戶端會打開令牌服務的后端服務器通道來檢索訪問令牌(access_token),

  2. 在后續會對這方面進行介紹繼續說明,資料庫持久化問題,以及如何應用在API資源服務器中和配置在客戶端中,會進一步說明,

  3. 如果有不對的或不理解的地方,希望大家可以多多指正,提出問題,一起討論,不斷學習,共同進步,

  4. 專案地址

六、附加

OpenID Connect資料

Grant Types 型別

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

標籤:.NET Core

上一篇:請教個LINQ問題

下一篇:一文說通C#中的異步迭代器

標籤雲
其他(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