1. 程式人生 > 遊戲 >《艾爾登法環》某幻影牆需要攻擊50次或為BUG

《艾爾登法環》某幻影牆需要攻擊50次或為BUG

.Net Core——JWT授權

關於JWT的基本概念,如果有不清晰的同學,請點選這裡,就不在這裡贅述了。接下來聊聊JWT是怎麼發揮作用的。

 

第一,安裝nuget包

Microsoft.AspNetCore.Authentication.JwtBearer

 

第二,配置【Startup】

首先是【ConfigureServices】方法,下面要寫一大堆進去

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(x =>
                {
x.RequireHttpsMetadata = false;
                x.SaveToken </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;

                x.TokenValidationParameters </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> TokenValidationParameters()
                {
                    ValidateLifetime </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,</span>
                    LifetimeValidator = (notBefore, expires, securityToken, validationParameters) =&gt;<span style="color: rgba(0, 0, 0, 1)">
                    {
                        </span><span style="color: rgba(0, 0, 255, 1)">bool</span> t = DateTime.UtcNow &lt;<span style="color: rgba(0, 0, 0, 1)"> expires;
                        </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> t;
                    },
ValidateAudience = false,
                    ValidateIssuer </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
                    ValidIssuer </span>=<span style="color: rgba(0, 0, 0, 1)"> jwtConfig.Issuer,

                    ValidateIssuerSigningKey </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
                    IssuerSigningKey </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.Key)),
                };
            });</span></span></pre>

雖然看起來多,實際上邏輯很清晰,我在這裡簡單解釋一下:

RequireHttpsMetadata:獲取或設定元資料地址或許可權是否需要HTTPS,預設為true

SaveToken:是否將資訊儲存在token中

TokenValidationParameters:這部分網上有很多版本,其中大部分都是寫滿的,但這對新手不太友好;而且也不是必須寫滿。先解釋一些程式碼裡的驗證開關(設定true、false的我稱為驗證開關)

ValidateLifetime——是否驗證過期時間

ValidateAudience——是否驗證被髮布者

ValidateIssuer——是否驗證釋出者

ValidateIssuerSigningKey——是否驗證簽名

檢視框架程式碼你會發現更多的驗證開關,這裡就不一一解釋了:

 

然後在【Configure】新增引用:

app.UseAuthentication();
app.UseAuthorization();

這裡的順序不能顛倒。第一行是開啟身份驗證,第二行是開啟授權。

 

第三,配置

JWT需要進行一些簡單的配置來確保安全,至於配置寫在哪裡都可以,我是放在appsettings內:

  "JWT": {
    "Issuer": "釋出者,一般是一個域名",
    "Key": "一個新的guid",
    "Expires": 600(秒)
  }

 

第四,生成JWT

為了方便大家理解,我這邊直接上程式碼:

     public static string GetToken(IOptions<JwtConfig> _options, dynamic customer)
        {
            var claims = new[] {
                new Claim(ClaimTypes.Name,"JWT"),
                new Claim("ID",customer.ID),
                new Claim("WxOpenID",customer.WxOpenID),
                new Claim("Father",customer.Father)
            };
        
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_options.Value.Key));
        </span><span style="color: rgba(0, 0, 255, 1)">var</span> credentials = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        </span><span style="color: rgba(0, 0, 255, 1)">var</span> token = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JwtSecurityToken(
           issuer: _options.Value.Issuer,
            claims: claims,
            expires: DateTime.UtcNow.AddMinutes(_options.Value.Expires),
            signingCredentials: credentials);

        </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JwtSecurityTokenHandler().WriteToken(token);
    }</span></span></pre>

如果在token中想要攜帶某些引數,可以使用Claim進行封裝。

接下來還有3個小步驟:

1、對配置檔案中的key進行加密,得到對稱加密key。

2、使用上一步得到的結果生成數字證書。

3、配置token的內容。

最後,就可以生成jwt並且返回了。

 

第五,獲取JWT內容

正常情況下,JWT除了做驗證以外,還要有一些引數做輔助。上面說了引數傳遞是通過定義claim實現的,那麼怎麼合法的解析呢?還是直接上程式碼:

     public static JwtInfo GetInfoFromToken(string token = null)
        {
            if (token is null)
                return null;
        </span><span style="color: rgba(0, 0, 255, 1)">string</span> tokenStr = token.Replace(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Bearer </span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">);

        </span><span style="color: rgba(0, 0, 255, 1)">var</span> handler = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JwtSecurityTokenHandler();

        </span><span style="color: rgba(0, 0, 255, 1)">var</span> payload =<span style="color: rgba(0, 0, 0, 1)"> handler.ReadJwtToken(tokenStr).Payload;

        </span><span style="color: rgba(0, 0, 255, 1)">var</span> claims =<span style="color: rgba(0, 0, 0, 1)"> payload.Claims;

        JwtInfo info </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JwtInfo()
        {
            ID </span>= claims.First(claim =&gt; claim.Type == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ID</span><span style="color: rgba(128, 0, 0, 1)">"</span>)?<span style="color: rgba(0, 0, 0, 1)">.Value,
            WxOpenID </span>= claims.First(claim =&gt; claim.Type == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">WxOpenID</span><span style="color: rgba(128, 0, 0, 1)">"</span>)?<span style="color: rgba(0, 0, 0, 1)">.Value,
            Father </span>= claims.First(claim =&gt; claim.Type == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Father</span><span style="color: rgba(128, 0, 0, 1)">"</span>)?<span style="color: rgba(0, 0, 0, 1)">.Value</span><span style="color: rgba(0, 0, 0, 1)">
        };

        </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> info;
    }</span></span></pre>

這一段沒什麼好講的,對應的名字拿到對應的引數。不過如果引數不存在這裡會報錯,所以儘量規範一點,首尾呼應。

 

第六,程式碼應用

JWT也生成了,同時也可以反向解析傳遞的引數了,該如何應用到程式碼中去呢?這裡要用到特性。

為需要進行驗證的控制器新增【Authorize】特性,這個控制器下的所有方法在外部呼叫時就都需要JWT認證才可順利呼叫,否則返回401(未授權)。如果不是全部方法都需要認證,那麼可以為方法新增【AllowAnonymous】特性來忽略認證限制,如圖:

 

最後

基於JWT可以延伸出更多玩法,同學們有好的想法歡迎討論。

 

關於JWT的基本概念,如果有不清晰的同學,請點選這裡,就不在這裡贅述了。接下來聊聊JWT是怎麼發揮作用的。

 

第一,安裝nuget包

Microsoft.AspNetCore.Authentication.JwtBearer

 

第二,配置【Startup】

首先是【ConfigureServices】方法,下面要寫一大堆進去

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(x =>
                {
                    x.RequireHttpsMetadata = false;
                x.SaveToken </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;

                x.TokenValidationParameters </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> TokenValidationParameters()
                {
                    ValidateLifetime </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,</span>
                    LifetimeValidator = (notBefore, expires, securityToken, validationParameters) =&gt;<span style="color: rgba(0, 0, 0, 1)">
                    {
                        </span><span style="color: rgba(0, 0, 255, 1)">bool</span> t = DateTime.UtcNow &lt;<span style="color: rgba(0, 0, 0, 1)"> expires;
                        </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> t;
                    },
ValidateAudience = false,
                    ValidateIssuer </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
                    ValidIssuer </span>=<span style="color: rgba(0, 0, 0, 1)"> jwtConfig.Issuer,

                    ValidateIssuerSigningKey </span>= <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
                    IssuerSigningKey </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.Key)),
                };
            });</span></span></pre>

雖然看起來多,實際上邏輯很清晰,我在這裡簡單解釋一下:

RequireHttpsMetadata:獲取或設定元資料地址或許可權是否需要HTTPS,預設為true

SaveToken:是否將資訊儲存在token中

TokenValidationParameters:這部分網上有很多版本,其中大部分都是寫滿的,但這對新手不太友好;而且也不是必須寫滿。先解釋一些程式碼裡的驗證開關(設定true、false的我稱為驗證開關)

ValidateLifetime——是否驗證過期時間

ValidateAudience——是否驗證被髮布者

ValidateIssuer——是否驗證釋出者

ValidateIssuerSigningKey——是否驗證簽名

檢視框架程式碼你會發現更多的驗證開關,這裡就不一一解釋了:

 

然後在【Configure】新增引用:

app.UseAuthentication();
app.UseAuthorization();

這裡的順序不能顛倒。第一行是開啟身份驗證,第二行是開啟授權。

 

第三,配置

JWT需要進行一些簡單的配置來確保安全,至於配置寫在哪裡都可以,我是放在appsettings內:

  "JWT": {
    "Issuer": "釋出者,一般是一個域名",
    "Key": "一個新的guid",
    "Expires": 600(秒)
  }

 

第四,生成JWT

為了方便大家理解,我這邊直接上程式碼:

     public static string GetToken(IOptions<JwtConfig> _options, dynamic customer)
        {
            var claims = new[] {
                new Claim(ClaimTypes.Name,"JWT"),
                new Claim("ID",customer.ID),
                new Claim("WxOpenID",customer.WxOpenID),
                new Claim("Father",customer.Father)
            };
        
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_options.Value.Key));
        </span><span style="color: rgba(0, 0, 255, 1)">var</span> credentials = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SigningCredentials(key, SecurityAlgorithms.HmacSha256);

        </span><span style="color: rgba(0, 0, 255, 1)">var</span> token = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JwtSecurityToken(
           issuer: _options.Value.Issuer,
            claims: claims,
            expires: DateTime.UtcNow.AddMinutes(_options.Value.Expires),
            signingCredentials: credentials);

        </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JwtSecurityTokenHandler().WriteToken(token);
    }</span></span></pre>

如果在token中想要攜帶某些引數,可以使用Claim進行封裝。

接下來還有3個小步驟:

1、對配置檔案中的key進行加密,得到對稱加密key。

2、使用上一步得到的結果生成數字證書。

3、配置token的內容。

最後,就可以生成jwt並且返回了。

 

第五,獲取JWT內容

正常情況下,JWT除了做驗證以外,還要有一些引數做輔助。上面說了引數傳遞是通過定義claim實現的,那麼怎麼合法的解析呢?還是直接上程式碼:

     public static JwtInfo GetInfoFromToken(string token = null)
        {
            if (token is null)
                return null;
        </span><span style="color: rgba(0, 0, 255, 1)">string</span> tokenStr = token.Replace(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Bearer </span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">""</span><span style="color: rgba(0, 0, 0, 1)">);

        </span><span style="color: rgba(0, 0, 255, 1)">var</span> handler = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JwtSecurityTokenHandler();

        </span><span style="color: rgba(0, 0, 255, 1)">var</span> payload =<span style="color: rgba(0, 0, 0, 1)"> handler.ReadJwtToken(tokenStr).Payload;

        </span><span style="color: rgba(0, 0, 255, 1)">var</span> claims =<span style="color: rgba(0, 0, 0, 1)"> payload.Claims;

        JwtInfo info </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> JwtInfo()
        {
            ID </span>= claims.First(claim =&gt; claim.Type == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">ID</span><span style="color: rgba(128, 0, 0, 1)">"</span>)?<span style="color: rgba(0, 0, 0, 1)">.Value,
            WxOpenID </span>= claims.First(claim =&gt; claim.Type == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">WxOpenID</span><span style="color: rgba(128, 0, 0, 1)">"</span>)?<span style="color: rgba(0, 0, 0, 1)">.Value,
            Father </span>= claims.First(claim =&gt; claim.Type == <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Father</span><span style="color: rgba(128, 0, 0, 1)">"</span>)?<span style="color: rgba(0, 0, 0, 1)">.Value</span><span style="color: rgba(0, 0, 0, 1)">
        };

        </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> info;
    }</span></span></pre>

這一段沒什麼好講的,對應的名字拿到對應的引數。不過如果引數不存在這裡會報錯,所以儘量規範一點,首尾呼應。

 

第六,程式碼應用

JWT也生成了,同時也可以反向解析傳遞的引數了,該如何應用到程式碼中去呢?這裡要用到特性。

為需要進行驗證的控制器新增【Authorize】特性,這個控制器下的所有方法在外部呼叫時就都需要JWT認證才可順利呼叫,否則返回401(未授權)。如果不是全部方法都需要認證,那麼可以為方法新增【AllowAnonymous】特性來忽略認證限制,如圖:

 

最後

基於JWT可以延伸出更多玩法,同學們有好的想法歡迎討論。

 

https://www.cnblogs.com/muchengqingxin/p/13972849.html