基於.NET6平台開發WebApi(十一)—— 使用JWT進行用戶鑒權


基於NET6平台WebApi嘗鮮項目: 基於最新的.NET6平台,完全拋棄繁雜的接口,采用.NET最經典的三層架構,結合簡化的DDD設計模式... (gitee.com)

至此我們的項目已經可以正常運行了,但是聰明的你可能發現了一個問題,那就是我們在第九章中將控制器基類中的[Authorize]標記注釋掉了,而且我們添加了一個CurrentUserId屬性,沒錯,它就是為了用戶鑒權使用的。用戶登錄可以說是WebApi必不可少的功能,本篇我們就來詳細說說如何進行用戶鑒權。

1、對於小型項目或者個人項目來說,可能規模比較小,而且不需要單點登錄這樣的功能,也就沒有必要去單獨建設一個IdentityServer服務器來實現鑒權,此處我們可以直接使用.NET自帶的功能來實現JWT簽發,首先我們打開Nuget,搜索安裝Microsoft.AspNetCore.Authentication.JwtBearer。

2、接着我們在appsettings.json中配置一個key用於JWT簽發,然后打開Program.cs,添加如下代碼

#region 添加校驗
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options =>
{
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidateIssuerSigningKey = true,
        ValidAudience = "net6api.com",
        ValidIssuer = "net6api.com",
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["JwtSecurityKey"])),
    };
});
#endregion
app.UseAuthentication();
app.UseAuthorization();

3、接下來我們創建一個LoginDto類用於用戶登錄信息輸入,一個LoginView用於用戶登錄信息返回,代碼如下

namespace NET6.Domain.Dtos
{
    /// <summary>
    /// 用戶登錄
    /// </summary>
    public class LoginDto
    {
        /// <summary>
        /// 登錄名
        /// </summary>
        public string LoginName { get; set; }
        /// <summary>
        /// 密碼
        /// </summary>
        public string Password { get; set; }
    }
}
namespace NET6.Domain.ViewModels
{
    /// <summary>
    /// 登錄信息
    /// </summary>
    public class LoginView
    {
        /// <summary>
        /// token
        /// </summary>
        public string Token { get; set; }
        /// <summary>
        /// 過期時間
        /// </summary>
        public DateTime Expires { get; set; }
        /// <summary>
        /// 用戶Id
        /// </summary>
        public string Id { get; set; }
        /// <summary>
        /// 用戶名稱
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 用戶頭像
        /// </summary>
        public string Avatar { get; set; }
    }
}

4、接着我們創建一個新的控制器,命名為AuthController,同樣繼承於BaseController,添加一個登錄方法,並且假設我們用戶信息已經驗證成功,我們給登錄方法加上[AllowAnonymous]標記並將BaseController中的[Authorize]標記啟用,代碼如下

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using NET6.Domain.Dtos;
using NET6.Domain.ViewModels;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace NET6.Api.Controllers
{
    /// <summary>
    /// 鑒權相關
    /// </summary>
    public class AuthController : BaseController
    {
        readonly IConfiguration _config;
        public AuthController(IConfiguration config)
        {
            _config = config;
        }

        /// <summary>
        /// 用戶登錄
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("login")]
        [ProducesResponseType(typeof(LoginView), StatusCodes.Status200OK)]
        public async Task<IActionResult> LoginAsync(LoginDto dto)
        {
            #region 校驗用戶信息,假設此處我們已經校驗成功

            #endregion
            var view = new LoginView
            {
                Expires = DateTime.Now.AddDays(30)
            };
            var claims = new[] { new Claim(ClaimTypes.NameIdentifier, "") };
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["JwtSecurityKey"]));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var token = new JwtSecurityToken(
                issuer: "net6api.com",
                audience: "net6api.com",
                claims: claims,
                expires: view.Expires,
                signingCredentials: creds);
            view.Token = new JwtSecurityTokenHandler().WriteToken(token);
            return Ok(JsonView(view));
        }
    }
}

4、編譯運行,我們直接訪問http://localhost:58707/address?page=1&size=15,發現返回401,表明請求未授權。

5、我們訪問用戶登錄接口,獲取Token。

6、我們使用Token再次訪問接口,發現鑒權通過,接口正常返回。

7、一切搞定之后我們該如何獲取用戶信息呢,直接訪問我們在BaseController中定義的CurrentUserId即可(可以將更多的信息添加到Token中,在此處同樣可以獲取)。

 


免責聲明!

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



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