基於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中,在此處同樣可以獲取)。