ASP.NET Core WebApi使用JWT認證


什么是JWT:https://www.cnblogs.com/yan7/p/7857833.html

在前后端分離開發中會需要進行用戶驗證,本篇博客介紹如何在ASP.NET Core WebApi中使用JWT進行用戶認證。

本篇博客延續上一篇博客 https://www.cnblogs.com/gygg/p/12849641.html 配置swagger驗證功能

開發工具:Visual Studio2019

目標框架:.NET Core 3.1

一、啟用swagger驗證功能

1.1、AddSwaggerGen()方法中啟用swagger驗證功能,添加全局安全條件,自定義Heard Token

services.AddSwaggerGen(c =>
{
    //啟用swagger驗證功能
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
    {
        Description = "在下框中輸入請求頭中需要添加Jwt授權Token:Bearer Token",
        Name = "Authorization",//jwt默認的參數名稱
        In = ParameterLocation.Header,//jwt默認存放authorization信息的位置(請求頭中)
        Type = SecuritySchemeType.ApiKey,
        BearerFormat = "JWT",
        Scheme = "Bearer"
    });
    //添加全局安全條件
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme{
                Reference = new OpenApiReference {
                            Type = ReferenceType.SecurityScheme,
                            Id = "Bearer"}
            },new string[] { }
        }
    });
    //顯示自定義的Heard Token
    c.OperationFilter<AuthTokenHeaderParameter>();
});

1.2、添加 AuthTokenHeaderParameter 類,顯示自定義的Heard Token

public class AuthTokenHeaderParameter : IOperationFilter
    {
        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            operation.Parameters = operation.Parameters ?? new List<OpenApiParameter>();
            var isAuthor = operation != null && context != null;
            if (isAuthor)
            {
                //in query header 
                operation.Parameters.Add(new OpenApiParameter()
                {
                    Name = "Authorization",
                    Description = "身份驗證",
                    Required = false,
                    In = ParameterLocation.Header
                });
            }
            if (!context.ApiDescription.HttpMethod.Equals("POST", StringComparison.OrdinalIgnoreCase) &&
               !context.ApiDescription.HttpMethod.Equals("PUT", StringComparison.OrdinalIgnoreCase))
            {
                return;
            }
        }
    }

啟動項目,效果圖如下

 

2、注冊JWT

2.1、添加 JWTTokenOptions 類

public class JWTTokenOptions
{
    /// <summary>
    /// 訂閱者
    /// </summary>
    public string Audience { get; set; }
    /// <summary>
    /// 發起人
    /// </summary>
    public string Issuer { get; set; }
    /// <summary>
    /// 過期時間 單位秒
    /// </summary>
    public long Expire { get; set; }
    /// <summary>
    /// 秘鑰
    /// </summary>
    public string Secret { get; set; }
}

2.2、在 appsettings.json 中配置JWTToken

"JWTToken": {
  "Expire": 3600, //token過期時間 單位s
  "Audience": "www.baidu.com", //訂閱者
  "Issuer": "baidu", //發起人
  "Secret": "************************" //秘鑰
}

2.3、在 startup 類的 ConfigureServices 方法中注冊 jwt

#region 注冊jwt
JWTTokenOptions JWTTokenOptions = new JWTTokenOptions();

//獲取appsettings的內容
services.Configure<JWTTokenOptions>(this.Configuration.GetSection("JWTToken"));
//將給定的對象實例綁定到指定的配置節
Configuration.Bind("JWTToken", JWTTokenOptions);

//注冊到Ioc容器
services.AddSingleton(JWTTokenOptions);

//添加驗證服務
services.AddAuthentication(option =>
{
    //默認身份驗證模式
    option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    //默認方案
    option.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

}).AddJwtBearer(option =>
{
    //設置元數據地址或權限是否需要HTTP
    option.RequireHttpsMetadata = false;
    option.SaveToken = true;
    //令牌驗證參數
    option.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        //獲取或設置要使用的Microsoft.IdentityModel.Tokens.SecurityKey用於簽名驗證。
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.
        GetBytes(JWTTokenOptions.Secret)),
        //獲取或設置一個System.String,它表示將使用的有效發行者檢查代幣的發行者。 
        ValidIssuer = JWTTokenOptions.Issuer,
        //獲取或設置一個字符串,該字符串表示將用於檢查的有效受眾反對令牌的觀眾。
        ValidAudience = JWTTokenOptions.Audience,
        //是否驗證發起人
        ValidateIssuer = false,
        //是否驗證訂閱者
        ValidateAudience = false,
        ////允許的服務器時間偏移量
        ClockSkew = TimeSpan.Zero,
        ////是否驗證Token有效期,使用當前時間與Token的Claims中的NotBefore和Expires對比
        ValidateLifetime = true
    };
    //如果jwt過期,在返回的header中加入Token-Expired字段為true,前端在獲取返回header時判斷
    option.Events = new JwtBearerEvents()
    {
        OnAuthenticationFailed = context =>
        {
            if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
            {
                context.Response.Headers.Add("Token-Expired", "true");
            }
            return Task.CompletedTask;
        }
    };
});
#endregion

2.4、在 startup 類的 Configure 方法中添加認證

app.UseAuthentication();  //添加認證
app.UseAuthorization();   //添加授權(.netCore 3.x中使用)

3、生成JWT

3.1、添加 TokenResult 類

public class TokenResult
{
    /// <summary>
    /// token字符串
    /// </summary>
    public string Access_token { get; set; }

    /// <summary>
    /// 過期時間
    /// </summary>
    public long Expires_in { get; set; }
}

3.2、添加 JwtTokenHelper 類

public class JwtTokenHelper
{
    public JwtTokenHelper()
    {
    }

    public TokenResult AuthorizeToken(int memberId, JWTTokenOptions _tokenOptions)
    {
        //基於聲明的認證
        var claims = new[]
        {
            new Claim(ClaimTypes.Name,memberId.ToString()),
            new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString())//jwt的唯一標識
        };
        //秘鑰 轉化成UTF8編碼的字節數組
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenOptions.Secret));
        var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);//資格證書 秘鑰加密
        var jwtToken = new JwtSecurityToken(_tokenOptions.Issuer, _tokenOptions.Audience, claims,//發起人 訂閱者
            expires: DateTime.Now.AddSeconds(_tokenOptions.Expire),//過期時間
            signingCredentials: credentials);//秘鑰
        var securityToken = new JwtSecurityTokenHandler().WriteToken(jwtToken);//序列化jwt格式

        //生成令牌字符串
        return new TokenResult()
        {
            Access_token = "Bearer " + securityToken,
            Expires_in = _tokenOptions.Expire
        };
    }
}

3.3、添加生成 JWT 方法

[ApiController]
[Route("api/[controller]/[action]")]
public class HomeController : Controller
{
    private readonly JWTTokenOptions _tokenOptions;
    public HomeController(JWTTokenOptions tokenOptions)
    {
        _tokenOptions = tokenOptions;
    }
    /// <summary>
    /// 生成jwt
    /// </summary>
    /// <returns></returns>
    [HttpPost]
    public TokenResult GenerateJwt()
    {
        var token = new JwtTokenHelper().AuthorizeToken(123456, _tokenOptions);
        return token;
    }
}

執行 GenerateJwt 方法,生成 jwt

在需要認證的 Controller 中添加 [Authorize] 特性

若未進行jwt認證,則報錯401

若進行了jwt 認證,則正常返回接口

End!


免責聲明!

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



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