.netcore實現jwt身份驗證


前言

http協議本身是一種無狀態的協議。所以客戶端的每次請求,服務端是不清楚其身份的,需要客戶端每次都要將身份信息傳入,服務進行驗證,才能達到安全驗證的目的。

傳統的Web用戶驗證:
1、客戶端傳入用戶名和密碼---2、后端驗證成功后保存session信息,並將session信息返回給客戶端--3、客戶端保存session信息到cookie中---
4、客戶端再請求需要的資源時,將cookie中的session信息傳給服務端--5、服務端驗證信息是否正確,正確則進行相應的操作,不正確則返回登錄頁面或者提示錯誤。

當然傳統的session-cookie方式是可以達到用戶身份驗證的目的,但是在分布式的場景下就不好使了。因為session是存在當時對應的服務器中的,當我們部署多台服務器,並采用了負載均衡時,session不共享時,只能在其驗證的服務器上才能通過,而無法達到多台服務器協同負載工作。(當然也可以通過將session信息存於數據庫或者是分布式緩存中,每次需要驗證時從數據庫或者緩存中獲取做驗證,但是這樣就多了一重數據庫操作,或者是緩存出問題時無法驗證)。

Token驗證模式:
1、客戶端使用用戶名密碼來請求服務器--2、服務器驗證用戶信息,成功則返回客戶端一個token信息--3、客戶端留存token信息,在每次請求時將token一並傳給服務端--4、服務端驗證token,正確則返回數據。

Jwt(Json web token), 是為了在網絡應用環境間傳遞聲明而執行的一種基於JSON的開放標准((RFC 7519).該token被設計為緊湊且安全的。它主要由3部分數據組成:頭部(header),載荷(payload),簽名(signature)。其實它就是token,服務端驗證成功后按照算法組成jwt,返回給客戶端;客戶端請求服務端附帶jwt,服務端驗證jwt正確性,正確則返回對應的數據

.netcore實現jwt身份驗證(同時集成swagger)

 1、在appsettings.json文件中配置(注意這些配置信息的安全性,特別是secretkey。secretkey長度一般要求16位或以上)

 "JwtSettings": {
    "Issuer": "john_yong",
    "Audience": "user",
    "SecretKey": "123456789123456789"
  },

 

2、在startup.cs的ConfigureServices(IServiceCollection services)方法中配置

     services.Configure<JwtSetting>(Configuration.GetSection("JwtSettings"));
     JwtSetting setting = new JwtSetting();
     Configuration.Bind("JwtSettings", setting); 

      #region swagger
            services.AddSwaggerGen(p =>
            {
                p.SwaggerDoc("v1", new Microsoft.OpenApi.Models.OpenApiInfo
                {
                    Version = "v1",
                    Title = "SimpleTest API 接口文檔",
                    //Contact = new OpenApiContact
                    //{
                    //    Name = "john_yong",
                    //    Email = "gxunet@163.com",
                    //    Url = new Uri("http://xxxx.com"),
                    //},
                });

                //p.OperationFilter<HttpHeaderOperation>(); // 添加httpHeader參數
                #region 啟用swagger驗證功能
                p.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
                {
                    Description = "在下框中輸入請求頭中需要添加Jwt授權Token:Bearer Token",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey,
                    BearerFormat = "JWT",
                    Scheme = "Bearer"
                });
                p.AddSecurityRequirement(new OpenApiSecurityRequirement
                        {
                            {
                                new OpenApiSecurityScheme
                                {
                                    Reference = new OpenApiReference {
                                        Type = ReferenceType.SecurityScheme,
                                        Id = "Bearer"
                                    }
                                },
                                new string[] { }
                            }
                        });
                #endregion
                // 為 Swagger JSON and UI設置xml文檔注釋路徑
                var xmlPath = Path.Combine(AppContext.BaseDirectory, "SimpleTestApplication.xml");
 
                p.IncludeXmlComments(xmlPath );
            });

            #endregion
            #region 添加驗證服務 
            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(p =>
                {
                    p.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = true,
                        ValidateAudience = true,
                        ValidateLifetime = true,
                        ClockSkew = TimeSpan.FromSeconds(30),
                        ValidateIssuerSigningKey = true,
                        ValidAudience = setting.Audience,
                        ValidIssuer = setting.Issuer,
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(setting.SecretKey))
                    };
                });
              #endregion

 

在 Configure(IApplicationBuilder app, IWebHostEnvironment env)方法中配置

   //啟用授權
            app.UseAuthentication();

            app.UseAuthorization();


JwtSetting.cs

 /// <summary>
    /// 
    /// </summary>
    public class JwtSetting
    {
        /// <summary>
        /// 證書頒發者
        /// </summary>
        public string Issuer { get; set; }

        /// <summary>
        ///  角色
        /// </summary>
        public string Audience { get; set; }

        /// <summary>
        /// 加密字符串
        /// </summary>
        public string SecretKey { get; set; }
    }

 

3、創建AuthController提供api驗證獲取jwt
    [ApiController]
    [Route("[controller]")]
    public class AuthController : Controller
    {
        private JwtSetting _jwtSettings;
        public AuthController(IOptions<JwtSetting> jwtSetting)
        {
            _jwtSettings = jwtSetting.Value;
        }
        /// <summary>
        /// 獲取token 
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="pwd"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpGet("getToken")]
        public ResponseFormatDto<TokenInfo> GetToken(string userName, string pwd)
        {
            double expiredMinute = 30;   //過期時間30分鍾
            DateTime expiredTime = DateTime.Now.AddMinutes(expiredMinute);
            //TODO驗證用戶
            if (userName == "admin" && pwd == "1234560")
            {
                var claims = new[]
                {
                    new Claim(JwtRegisteredClaimNames.Nbf,$"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}") ,
                    new Claim (JwtRegisteredClaimNames.Exp,$"{new DateTimeOffset(expiredTime).ToUnixTimeSeconds()}"),
                    new Claim(ClaimTypes.Name, userName)
                };
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.SecretKey));
                var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
                var jwtSecurityToken = new JwtSecurityToken(
                    issuer: _jwtSettings.Issuer,
                    audience: _jwtSettings.Audience,
                    claims: claims,
                    expires: expiredTime,
                    signingCredentials: creds);
                string token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
                TokenInfo tokenInfo = new TokenInfo()
                {
                    Token = token,
                    Expired = expiredTime
                };
                return HelperTool.GetResponse(tokenInfo);

            }
            else
            {
                return HelperTool.GetResponse<TokenInfo>(null, Status.Fail, "username or password is incorrect.");
            }
        }
    }

 

TokenInfo.cs

    /// <summary>
    /// token information
    /// </summary>
    public class TokenInfo
    {
        /// <summary>
        /// token
        /// </summary>
        public string Token { get; set; }
        /// <summary>
        /// 過期時間
        /// </summary>
        public DateTime Expired { get; set; }

    }

 

HelperTool.cs是簡單通用的構造統一的返回實體ResponseFormatDto(此處略)



結果示例







-------------------------------------
以上就是jwt的簡單介紹以及應用。但是在實際項目中(特別是微服務流行的當下),用戶驗證、token管理一般不會在業務項目中實現的,基本上都是建立用戶中心管理用戶,鑒權用戶信息,生成token等。
一般用Identity 4實現的,實際的業務項目則是提供token參數傳入,在用戶中心中驗證。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM