ASP.Net Core 3.0 에서 JWT 인증 사용 실현

13934 단어 ASP.NetCoreJWT인증
JWT 인증 안내
Jwt 에 대한 소 개 는 인터넷 에 많 습 니 다.여 기 는 군말 이 아 닙 니 다.우 리 는 주로 jwt 의 구 조 를 봅 니 다.
JWT 는 주로 세 부분 으로 구성 되 는데 다음 과 같다.

HEADER.PAYLOAD.SIGNATURE
HEADER 은 token 의 메타 데 이 터 를 포함 하 는데 주로 암호 화 알고리즘 과 서명 의 유형 입 니 다.예 를 들 어 아래 의 정보 와 같이 설명 합 니 다.
암호 화 된 대상 유형 은 JWT 이 고 암호 화 알고리즘 은 HMAC SHA-256 입 니 다.

{"alg":"HS256","typ":"JWT"}
그리고 BASE 64 인 코딩 을 통 해 token 에 저장 해 야 합 니 다.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9  
Payload 은 주로 성명 정보(clam)를 포함 하 는데 이 성명 들 은 key-value 가 맞 는 데이터 구조 이다.
일반적으로 사용자 이름,캐릭터 등 정보,만 료 날짜 등 은 암호 화 되 지 않 았 기 때문에 민감 한 정 보 를 저장 하 는 것 을 권장 하지 않 습 니 다.

{"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name":"admin","exp":1578645536,"iss":"webapi.cn","aud":"WebApi"}
BASE 64 인 코딩 으로 token 에 저장 해 야 합 니 다.

eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiYWRtaW4iLCJleHAiOjE1Nzg2NDU1MzYsImlzcyI6IndlYmFwaS5jbiIsImF1ZCI6IldlYkFwaSJ9
Signature jwt 는 jws(JSon Web Signature)의 표준 에 맞 게 최종 서명 을 생 성 해 야 합 니 다.인 코딩 된 Header 와 Payload 정 보 를 합 친 다음 HmacSHA 256 과 같은 강력 한 암호 화 알고리즘 을 사용 하여 암호 화 합 니 다.HS256(BASE64(Header).Base64(Payload),secret)

2_akEH40LR2QWekgjm8Tt3lesSbKtDethmJMo_3jpF4
마지막 으로 생 성 된 token 은 다음 과 같 습 니 다.

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiYWRtaW4iLCJleHAiOjE1Nzg2NDU1MzYsImlzcyI6IndlYmFwaS5jbiIsImF1ZCI6IldlYkFwaSJ9.2_akEH40LR2QWekgjm8Tt3lesSbKtDethmJMo_3jpF4
개발 환경
프레임 워 크:asp.net 3.1
IDE:VS2019
ASP.NET 3.1 Webapi 에서 JWT 인증 사용
명령 행 에서 다음 명령 을 실행 하고 webapix 프로젝트 를 만 듭 니 다.

dotnet new webapi -n Webapi -o WebApi
특히 주의 할 때 3.x 기본 값 은 jwt 의 Microsoft.AspNetCore.Authentication.JwtBearer 라 이브 러 리 가 없 기 때문에 수 동 으로 NuGet Package 를 추가 하고 프로젝트 가 있 는 디 렉 터 리 로 전환 하여.net cli 명령 을 실행 해 야 합 니 다.

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer --version 3.1.0
jwt 를 서명 하거나 검증 할 때 사용 하 는 정 보 를 저장 하기 위해 간단 한 POCO 클래스 를 만 듭 니 다.

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Webapi.Models

{
  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; }
  }
}
그리고 appsettings.Development.json 에 jwt 가 사용 하 는 설정 정 보 를 추가 합 니 다(생 성 환경 이 라면 appsettings.json 에 추가 하면 됩 니 다)

"tokenManagement": {
    "secret": "123456",
    "issuer": "webapi.cn",
    "audience": "WebApi",
    "accessExpiration": 30,
    "refreshExpiration": 60
  }
그리고 startup 류 의 Configure Services 방법 에 설정 정 보 를 추가 합 니 다.

public void ConfigureServices(IServiceCollection services)
    {
      services.AddControllers();
      services.Configure<TokenManagement>(Configuration.GetSection("tokenManagement"));
      var token = Configuration.GetSection("tokenManagement").Get<TokenManagement>();

    }
지금까지 저 희 는 기본 적 인 작업 을 마 쳤 습 니 다.다음은 webapi 에 jwt 의 인증 서 비 스 를 주입 하고 미들웨어 파이프 에서 authentication 미들웨어 를 사용 합 니 다.
startup 클래스 에서 jwt 인증 서비스의 네 임 스페이스 를 참조 합 니 다.

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
그리고 ConfigureServices 방법 에 다음 과 같은 논 리 를 추가 합 니 다.

services.AddAuthentication(x =>
      {
        x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
      }).AddJwtBearer(x =>
      {
        x.RequireHttpsMetadata = false;
        x.SaveToken = true;
        x.TokenValidationParameters = new TokenValidationParameters
        {
          ValidateIssuerSigningKey = true,
          IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(token.Secret)),
          ValidIssuer = token.Issuer,
          ValidAudience = token.Audience,
          ValidateIssuer = false,
          ValidateAudience = false
        };
      });
Configure 방법 에서 인증 사용 하기

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();
      });
    }
위 에서 JWT 검증 기능 을 완 료 했 으 니 토 큰 발급 논 리 를 추가 해 야 한다.사용자 인증 과 token 발급 을 위 한 컨트롤 러 를 추가 해 야 합 니 다.AuthenticationController 이 라 고 명명 하 는 동시에 요청 한 DTO 류 를 추가 해 야 합 니 다.

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


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

[Route("api/[controller]")]
  [ApiController]
  public class AuthenticationController : ControllerBase
  {
    [AllowAnonymous]
     [HttpPost, Route("requestToken")]
    public ActionResult RequestToken([FromBody] LoginRequestDTO request)
    {
      if (!ModelState.IsValid)
      {
        return BadRequest("Invalid Request");
      }

      return Ok();

    }
  }
현재 위의 컨트롤 러 는 기본 적 인 논리 만 실현 하고 있 습 니 다.다음은 token 을 발급 하 는 서 비 스 를 만들어 구체 적 인 업 무 를 완성 해 야 합 니 다.첫 번 째 단 계 는 저희 가 먼저 대응 하 는 서비스 인 터 페 이 스 를 만 들 고 IAuthenticateService 이 라 고 명명 합 니 다.

public interface IAuthenticateService
  {
    bool IsAuthenticated(LoginRequestDTO request, out string token);
  }
이어서 인터페이스 실현

public class TokenAuthenticationService : IAuthenticateService
  {
    public bool IsAuthenticated(LoginRequestDTO request, out string token)
    {
      throw new NotImplementedException();
    }
  }
StartupConfigureServices 방법 에 서 비 스 를 등록 합 니 다.

services.AddScoped<IAuthenticateService, TokenAuthenticationService>();
Controller 에 IAuthenticateService 서 비 스 를 주입 하고 action 을 보완 합 니 다.

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");

    }
  }
정상 적 인 상황 에서 저 희 는 요청 한 사용자 와 비밀번호 에 따라 사용자 가 합 법 적 인지 검증 하고 데이터 베 이 스 를 연결 하여 데 이 터 를 가 져 와 검증 해 야 합 니 다.저 희 는 편 의 를 위해 모든 요청 한 사용자 가 합 법 적 이 라 고 가정 합 니 다.
여기에 사용자 가 관리 하 는 서 비 스 를 따로 추가 하고 IAuthenticateService 라 는 서비스 에 해당 하 는 논 리 를 추가 하지 않 으 며 주로 을 따 랐 다.우선 위 와 마찬가지 로 서비스 인터페이스 IUserService 을 만 듭 니 다.

public interface IUserService
  {
    bool IsValid(LoginRequestDTO req);
  }
IUserService 인터페이스 실현

public class UserService : IUserService
  {
    //    ,          
    public bool IsValid(LoginRequestDTO req)
    {
      return true;
    }
  }
같은 용기 에 등록

services.AddScoped<IUserService, UserService>();
그 다음 에 Token AuthenticationService 가 token 을 발급 하 는 논 리 를 보완 하려 면 먼저 IUserService 와 Token Management 를 주입 한 다음 에 구체 적 인 업무 논 리 를 실현 해 야 한다.이 token 의 생 성 또는 사용 하 는 Jwt 라 이브 러 리 가 제공 하 는 api 는 구체 적 으로 상세 하 게 설명 하지 않 는 다.
특히 Token Management 의 주입 은 IOptions 의 인터페이스 형식 으로 주입 되 었 습 니 다.Startpup 에서 기억 하 십 니까?저 희 는 설정 항목 을 통 해 TokenManagement 유형 을 등록 합 니 다.

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;

    }
  }
테스트 에 사용 할 API 를 준비 하고 Authorize 특성 을 눌 러 인증 이 필요 함 을 표시 합 니 다!

[ApiController]
  [Route("[controller]")]
  [Authorize]
  public class WeatherForecastController : ControllerBase
  {
    private static readonly string[] Summaries = new[]
    {
      "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
      _logger = logger;
    }

    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
      var rng = new Random();
      return Enumerable.Range(1, 5).Select(index => new WeatherForecast
      {
        Date = DateTime.Now.AddDays(index),
        TemperatureC = rng.Next(-20, 55),
        Summary = Summaries[rng.Next(Summaries.Length)]
      })
      .ToArray();
    }
  }
테스트 검증 을 지원 합 니 다.저 희 는 potman 을 사용 하여 http 요청 을 할 수 있 습 니 다.http 서 비 스 를 먼저 시작 하고 url 을 가 져 올 수 있 습 니 다.먼저 방문 에 권한 이 필요 한 인 터 페 이 스 를 테스트 할 수 있 지만 token 정 보 를 가지 고 있 지 않 습 니 다.되 돌아 오 는 것 은 401 입 니 다.권한 이 없 음 을 표시 합 니 다.

다음 에 인증 인 터 페 이 스 를 통 해 token 을 가 져 왔 는데 오류 가 발생 했 습 니 다.조회 해 보 니 HS 256 알고리즘 의 비밀 키 길 이 는 최신 128 비트 이 고 문자 가 최소 16 글자 로 바 뀌 었 습 니 다.이전에 설정 한 비밀 키 는 123456 이 므 로 이상 이 발생 했 습 니 다.

System.ArgumentOutOfRangeException: IDX10603: Decryption failed. Keys tried: 'HS256'. Exceptions caught: '128'. token: '48' (Parameter 'KeySize') at
비밀 키 업데이트

 "tokenManagement": {
    "secret": "123456123456123456",
    "issuer": "webapi.cn",
    "audience": "WebApi",
    "accessExpiration": 30,
    "refreshExpiration": 60
  }
다시 요청,token 가 져 오기 성공eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiYWRtaW4iLCJleHAiOjE1Nzg2NDUyMDMsImlzcyI6IndlYmFwaS5jbiIsImF1ZCI6IldlYkFwaSJ9.AehD8WTAnEtklof2OJsvg0U4_o8_SjdxmwUjzAiuI-o
token 을 이전에 요청 한 api 에 가 져 가서 재 테스트 하여 데 이 터 를 성공 적 으로 가 져 왔 습 니 다.
총화
token 의 인증 방식 을 바탕 으로 분포 식/소나무 결합 시스템 을 구축 하 는 것 이 더욱 쉽 습 니 다.어디서 든 생 성 된 token 은 같은 비밀 키 만 있 으 면 어디서 든 서명 검 사 를 할 수 있 습 니 다.
물론 jwt 인증 방식 을 잘 사용 해 야 합 니 다.그리고 다른 안전 세부 사항 도 처리 해 야 합 니 다.예 를 들 어 palyload 에 민감 한 정 보 를 저장 할 수 없고 https 의 암호 화 전송 방식 을 사용 하 는 등 업무 의 실제 수요 에 따라 더욱 안전 하고 보강 할 수 있 습 니 다!
또한 token 을 사용 하면 쿠키 의 제한 에서 벗 어 날 수 있다 는 것 을 발 견 했 기 때문에 JWT 는 모 바 일 앱 개발 의 최 우선 선택 입 니 다!
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기