.net core 3.1 jwt認證


  1. 首先在Visual Studio中創建一個WebApi項目;
  2. 引入nuget包:Microsoft.AspNetCore.Authentication.JwtBearer
  3. 在appsetting.json中配置jwt參數
"tokenConfig": {
    "secret": "D96BFA5B-F2AF-45BC-9342-5A55C3F9BBB0",
    "issuer": "test.cn",
    "audience": "test",
    "accessExpiration": 30,
    "refreshExpiration": 60
  }
  1. 編寫對應的token對象:
using Newtonsoft.Json;

namespace JwtDemo
{
    public class TokenManagement
    {
        [JsonProperty("secret")]
        public string Secret { get; set; }

        [JsonProperty("issuer")]
        public string Issuer { get; set; }

        [JsonProperty("audience")]
        public string Audience { get; set; }

        [JsonProperty("accessExpiration")]
        public int AccessExpiration { get; set; }

        [JsonProperty("refreshExpiration")]
        public int RefreshExpiration { get; set; }
    }
}
  1. 在Startup中配置啟用token認證
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;
using static JwtDemo.LoginRequestDTO;

namespace JwtDemo
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.Configure<TokenManagement>(Configuration.GetSection("tokenConfig"));

            var token = Configuration.GetSection("tokenConfig").Get<TokenManagement>();

            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(x =>
            {
                x.RequireHttpsMetadata = false;
                x.SaveToken = true;
                //Token Validation Parameters
                x.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    //獲取或設置要使用的Microsoft.IdentityModel.Tokens.SecurityKey用於簽名驗證。
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.
                    GetBytes(token.Secret)),
                    //獲取或設置一個System.String,它表示將使用的有效發行者檢查代幣的發行者。
                    ValidIssuer = token.Issuer,
                    //獲取或設置一個字符串,該字符串表示將用於檢查的有效受眾反對令牌的觀眾。
                    ValidAudience = token.Audience,
                    ValidateIssuer = false,
                    ValidateAudience = false,
                };
            });
            services.AddScoped<IAuthenticateService, TokenAuthenticationService>();
            services.AddScoped<IUserService, UserService>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseAuthentication();
            
            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

  1. 編寫認證服務接口及服務類
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using System;
using System.ComponentModel.DataAnnotations;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace JwtDemo
{
    public interface IAuthenticateService
    {
        bool IsAuthenticated(LoginRequestDTO request, out string token);
    }

    public class LoginRequestDTO
    {
        [Required]
        [JsonProperty("username")]
        public string Username { get; set; }


        [Required]
        [JsonProperty("password")]
        public string Password { get; set; }

        /// <summary>
        /// token認證服務
        /// </summary>
        public class TokenAuthenticationService : IAuthenticateService
        {
            private readonly IUserService _userService;
            private readonly TokenManagement _tokenManagement;
            public TokenAuthenticationService(IUserService userService, IOptions<TokenManagement> tokenManagement)
            {
                _userService = userService;
                _tokenManagement = tokenManagement.Value;
            }
            public bool IsAuthenticated(LoginRequestDTO request, out string token)
            {
                token = string.Empty;
                if (!_userService.IsValid(request))
                    return false;
                var claims = new[]
                {
                new Claim(ClaimTypes.Name,request.Username)
            };
                var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenManagement.Secret));
                var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
                var jwtToken = new JwtSecurityToken(_tokenManagement.Issuer, _tokenManagement.Audience, claims,
                    expires: DateTime.Now.AddMinutes(_tokenManagement.AccessExpiration),
                    signingCredentials: credentials);
                token = new JwtSecurityTokenHandler().WriteToken(jwtToken);
                return true;
            }
        }

    }

}

  1. 自定義認證接口及類IUserService和UserService,模擬驗證密碼的過程,這個需要在Startup中配置注入服務
namespace JwtDemo
{
    public interface IUserService
    {
        bool IsValid(LoginRequestDTO req);
    }

    public class UserService : IUserService
    {
        //模擬測試,默認都是人為驗證有效
        public bool IsValid(LoginRequestDTO req)
        {
            return true;
        }
    }
}
  1. 添加AuthenticationController,用於根據用戶名和密碼獲取token
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace JwtDemo.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AuthenticationController : ControllerBase
    {
        private readonly IAuthenticateService _authService;
        public AuthenticationController(IAuthenticateService authService)
        {
            this._authService = authService;
        }

        [AllowAnonymous]
        [HttpPost, Route("requestToken")]
        public ActionResult RequestToken([FromBody] LoginRequestDTO request)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest("Invalid Request");
            }

            string token;
            if (_authService.IsAuthenticated(request, out token))
            {
                return Ok(token);
            }

            return BadRequest("Invalid Request");
        }

    }
}
  1. 測試:測試之前先給WeatherForecastController加上[Authorize],身份驗證之后才能訪問
  • 先訪問https://localhost:44324/weatherforecast,結果為401,未授權,

  • 下面請求token:

獲取到token:

帶token訪問被保護的webapi:

成功獲取到webapi數據:

通過學習了解了基本的jwt認證的使用方法
學會了在Fiddler中測試webapi
源碼:https://gitee.com/Alexander360/LearnIdentity/tree/master/LearnIdentity


免責聲明!

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



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