Asp.net-Mvc

JWT 身份驗證 ASP.NET Core MVC 應用程序

  • December 3, 2021

我已經看到了許多關於如何將 JWT 身份驗證與 Angular、React、Vue 等客戶端一起使用的範例,但找不到任何將 JWT 身份驗證與 ASP.NET Core(特別是 2.2)Web App Mvc 一起使用的範例。

有沒有人有任何關於如何做到這一點的例子或建議?

謝謝,

您可以使用基於 nuget 包 JWT 3.0.3 的此類

using JWT;
using JWT.Algorithms;
using JWT.Serializers;
using Newtonsoft.Json;
using System;

namespace Common.Utils
{
 public class JwtToken
 {
   private IJwtEncoder encoder;
   private IJwtDecoder decoder;

   /// <remarks>
   /// This requires a key value randomly generated and stored in your configuration settings. 
   /// Consider that it is a good practice use keys as at least long as the output digest bytes 
   /// length produced by the hashing algorithm used. Since we use an HMAC-SHA-512 algorithm, 
   /// then we can provide it a key at least 64 bytes long.
   /// <see cref="https://tools.ietf.org/html/rfc4868#page-7"/>
   /// </remarks>
   public string SecretKey { get; set; } 

   public JwtToken()
   {
       IJwtAlgorithm algorithm = new HMACSHA512Algorithm();
       IJsonSerializer serializer = new JsonNetSerializer();
       IDateTimeProvider datetimeProvider = new UtcDateTimeProvider();
       IJwtValidator validator = new JwtValidator(serializer, datetimeProvider);
       IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();

       encoder = new JwtEncoder(algorithm, serializer, urlEncoder);
       decoder = new JwtDecoder(serializer, validator, urlEncoder);
       SecretKey = "";
   }

   public JwtToken(string secretKey) : this()
   {
       SecretKey = secretKey;
   }

   public bool IsTokenValid(string token)
   {
       return !string.IsNullOrWhiteSpace(DecodeToken(token));
   }

   public string GetToken(object payload)
   {
       try
       {
           return encoder.Encode(payload, SecretKey);
       }
       catch (Exception)
       {
           return encoder.Encode(new DataModel(payload), SecretKey);
       }
   }

   public string DecodeToken(string token)
   {
       try
       {
           if (string.IsNullOrWhiteSpace(token) || token == "null")
           {
               return null;
           }
           return decoder.Decode(token, SecretKey, true);
       }
       catch (TokenExpiredException)
       {
           return null;
       }
       catch (SignatureVerificationException)
       {
           return null;
       }
   }

   public T DecodeToken<T>(string token) where T : class
   {
       try
       {
           if (string.IsNullOrWhiteSpace(token))
           {
               return null;
           }
           return decoder.DecodeToObject<T>(token, SecretKey, true);
       }
       catch (TokenExpiredException)
       {
           return null;
       }
       catch (SignatureVerificationException)
       {
           return null;
       }
       catch (Exception)
       {
           var data = decoder.DecodeToObject<DataModel>(token, SecretKey, true).Data;
           return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(data));
       }
   }
 }

 public class DataModel
 {
   public DataModel(object data)
   {
       Data = data;
   }
   public object Data { get; set; }
 }
}

然後在您的StartupConfigure方法中設置 jwt 中間件以檢查每個請求的身份驗證狀態:

app.Use((context, next) =>
       {

           // verify app access token if not another service call
           var appAccessToken = context.Request.Headers["Authorization"];
           if (appAccessToken.Count == 0)
           {
               context.Items["User"] = null;
           }
           else
           {
               var token = appAccessToken.ToString().Replace("Bearer ", "");
               var jwtToken = new JwtToken(config.JwtTokenSecret); //you need a secret (with requirements specified above) in your configuration (db, appsettings.json)
               if (string.IsNullOrWhiteSpace(token) || !jwtToken.IsTokenValid(token))
               {
                   context.Response.StatusCode = 401;
                   return Task.FromResult(0);
               }

               dynamic user = jwtToken.DecodeToken<dynamic>(token);

               var cachedToken = cache.Get(user.Id);  //you need some cache for store your token after login success and so can check against
               if (cachedToken == null || cachedToken.ToString() != token)
               {
                   context.Response.StatusCode = 401;
                   return Task.FromResult(0);
               }

               context.Items["User"] = new Dictionary<string, string>() {
                       { "FullName",user.Name?.ToString()},
                       { "FirstName",user.FirstName?.ToString()},
                       { "LastName",user.LastName?.ToString()},
                       { "Role",user.Role?.ToString()},
                       { "Email",user.Email?.ToString()}
                   };
           }
           return next();
       });

最後,您需要生成令牌並在身份驗證後返回它:

   [AllowAnonymous]
   public IActionResult Login(string username, string password)
   {
       User user = null; //you need some User class with the structure of the previous dictionary
       if (checkAuthenticationOK(username, password, out user)) //chackAuthenticationOk sets the user against db data after a succesfull authentication
       {
          var token = new JwtToken(_config.JwtTokenSecret).GetToken(user);  //_config is an object to your configuration
          _cache.Set(user.id, token);  //store in the cache the token for checking in each request
          return Ok(token);
       }

       return StatusCode(401, "User is not authorized");
   }

引用自:https://stackoverflow.com/questions/54559562