asp net core 2.1 jwt 를 어떻게 사용 하 는 지 원리 에서 정통 까지(2)

10609 단어 core2.1jwt의 원리
aspnet core 에서 jwt 파이프 인증 사용자 정의
전절 의 내용 을 바탕 으로 하 는 것 도 매우 쉽다.관건 은 미들웨어 이다.테스트 류 에서 의 사용자 정의 검증 을 미들웨어 에 넣 으 면 된다.
그러나 주의해 야 할 것 은 중간 부품 의 위치 가 매우 중요 하기 때문에 그 뒤의 파이프 만 영향 을 받 을 수 있다.
그러면 우 리 는 먼저 사용자 정의 미들웨어 류 를 만 듭 니 다.(미들웨어 의 상세 한 내용 은 여기 서 말 하지 않 겠 습 니 다.여러분 은 홈 페이지 와 다른 박문 을 참고 하 실 수 있 습 니 다)

/// <summary>
 ///         
 /// </summary>
 public class JwtCustomerAuthorizeMiddleware
 {
  private readonly RequestDelegate next;

  public JwtCustomerAuthorizeMiddleware(RequestDelegate next, string secret, List<string> anonymousPathList)
  {
   #region      jwt    
   if(!string.IsNullOrEmpty(secret))
   {
    TokenContext.securityKey = secret;
   }
   #endregion
   this.next = next;
   UserContext.AllowAnonymousPathList.AddRange(anonymousPathList);
  }

  public async Task Invoke(HttpContext context, UserContext userContext,IOptions<JwtOption> optionContainer)
  {
   if (userContext.IsAllowAnonymous(context.Request.Path))
   {
    await next(context);
    return;
   }

   var option = optionContainer.Value;

   #region     ,     Ruser 
 
   var result = context.Request.Headers.TryGetValue("Authorization", out StringValues authStr);
   if (!result || string.IsNullOrEmpty(authStr.ToString()))
   {
    throw new UnauthorizedAccessException("   ");
   }
   result = TokenContext.Validate(authStr.ToString().Substring("Bearer ".Length).Trim(), payLoad =>
   {
    var success = true;
    //           ,        
    //      aud     roberAudience
    success = success && payLoad["aud"]?.ToString() == option.Audience;
    if (success)
    {
     //  Ruse , user    payLoad ,(   jwt           payLoad ruser  )
     //         ,       ,payLoad      Key 
     userContext.TryInit(payLoad["ruser"]?.ToString());
    }
    return success;
   });
   if (!result)
   {
    throw new UnauthorizedAccessException("   ");
   }

   #endregion
   #region     
   if (!userContext.Authorize(context.Request.Path))
   {
    throw new UnauthorizedAccessException("   ");
   }
   #endregion

   await next(context);
  }
 }
위 에 있 는 이 미들웨어 에는 UserContext 온라인 문 이 있 습 니 다.이 종 류 는 현재 사용자 정보 와 권한 을 관리 하고 다른 정 보 는 잠시 상관 하지 않 습 니 다.우 리 는 먼저 이 중간 부품 의 검증 절차 가 어떤 지 살 펴 보 자.
이 미들웨어 는 주로 방문 경 로 를 검증 하 는 것 입 니 다.물론 다른 정보 에 대해 서도 검증 할 수 있 습 니 다.예 를 들 어(컨트롤 러 이름,동작 이름 등)
  • 현재 url 에 익명 으로 접근 할 수 있 는 지 확인 하고 가능 하 다 면 직접 통과 하여 검증 하지 않 습 니 다.익명 으로 접근 할 수 있 는 경로 가 아니라면
  • 을 계속 하 세 요.
  • 현재 http 머리 에 지 니 고 있 는 jwt(머리 에 저 장 된 Authorization)가 져 오기;
  • 은 앞에서 말 한 TokenContext 를 사용 하여 필요 한 검증 과 사용자 정의 복잡 한 검증 을 합 니 다.
  • 현재 방문 한 사용자 정 보 를 얻 습 니 다.저 희 는 사용자 의 기본 정 보 를 payLoad["ruser"]에 두 었 습 니 다.코드 가
  • 을 어떻게 조작 하 는 지 보 세 요.
  • 은 지금까지 인증 을 한 것 으로 당신 이 신분 이 있 는 사람 임 을 나타 낸다.다음은 권한 검증 을 하 는 것 입 니 다.당신 은 신분 이 있 는 사람 입 니 다.당신 이 아무 데 나 방문 하 는 사람 이 아니 라 는 것 을 의미 합 니 다.어떤 url 이나 action 에 접근 할 수 있 으 면 권한 검증 을 받 아야 합 니 다
  • 저 희 는 권한 검증 을 userContext.Authorize 방법 에 넣 습 니 다.(여기 서 어떻게 조작 하 는 지 깊이 설명 하지 않 습 니 다.기본 원 리 는 데이터 베이스 나 캐 시 에서 현재 사용자 가 대응 하 는 권한 목록,즉 url 목록 을 가 져 와 비교 하 는 것 입 니 다)
  • 사용자 정의 미들웨어 는 jwt 를 사용 하여 이러한 내용 을 검증 합 니 다.느낌 이 뚜렷 하고 간단 하 며 나무 가 있 습 니 다.
    중간 에 완성 되 었 습 니 다.다음 에 사용 하 겠 습 니 다.startup 의 Configure 방법 에 다음 코드 를 추가 하 겠 습 니 다.
    
    app.UseMiddleware<JwtCustomerAuthorizeMiddleware>(Configuration["JwtOption:SecurityKey"], new List<string>() { "/api/values/getjwt","/" });
    물론 위 에서 익명 으로 접근 할 수 있 는 url 도 appsetting.json 파일 에 정의 할 수 있 으 며,스스로 시도 할 수 있 습 니 다.
    어떻게 사용자 정의 정책 형식 을 통 해 사용자 정의 jwt 검증 을 실현 합 니까?
    사용자 정의 정책 에 대한 자세 한 소 개 는 홈 페이지 를 참고 할 수 있 습 니 다.자세 한 소 개 는 하지 않 습 니 다.
    우선 코드 를 올 리 고 사용자 정의 정책 을 만 드 는 데 매우 중요 한 두 가지 종 류 를 만 듭 니 다.다음 과 같 습 니 다.
    
    public class CommonAuthorizeHandler : AuthorizationHandler<CommonAuthorize>
     {
      /// <summary>
      ///          ,        JwtCustomerauthorizeMiddleware     
      /// </summary>
      /// <param name="context"></param>
      /// <param name="requirement"></param>
      /// <returns></returns>
      protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CommonAuthorize requirement)
      {
       var httpContext = (context.Resource as AuthorizationFilterContext).HttpContext;
       var userContext = httpContext.RequestServices.GetService(typeof(UserContext)) as UserContext;
    
       var jwtOption = (httpContext.RequestServices.GetService(typeof(IOptions<JwtOption>)) as IOptions<JwtOption>).Value;
    
       #region     ,     Ruser 
    
       var result = httpContext.Request.Headers.TryGetValue("Authorization", out StringValues authStr);
       if (!result || string.IsNullOrEmpty(authStr.ToString()))
       {
        return Task.CompletedTask;
       }
       result = TokenContext.Validate(authStr.ToString().Substring("Bearer ".Length).Trim(), payLoad =>
       {
        var success = true;
        //           ,        
        //      aud     roberAudience
        success = success && payLoad["aud"]?.ToString() == jwtOption.Audience;
        if (success)
        {
         //  Ruse , user    payLoad ,(   jwt           payLoad ruser  )
         //         ,       ,payLoad      Key 
         userContext.TryInit(payLoad["ruser"]?.ToString());
        }
        return success;
       });
       if (!result)
       {
        return Task.CompletedTask;
       }
    
       #endregion
       #region     
       if (!userContext.Authorize(httpContext.Request.Path))
       {
        return Task.CompletedTask;
       }
       #endregion
    
       context.Succeed(requirement);
       return Task.CompletedTask;
      }
     }
     public class CommonAuthorize: IAuthorizationRequirement
     {
    
     }
    그 중 두 가지 중요 한 종 류 는 어느 두 가지 입 니까?그들의 역할 은 또 무엇 입 니까?
    1.CommonAuthorize:IAuthorizationRequirement 은 어떤 이름 을 짓 는 지 에 대해 스스로 정의 하지만 반드시 IAuthorizationRequirement 을 계승 해 야 한다.이런 것들 은 초기 화 값 을 싣 고 Handler 에 전달 하여 논리 연산 을 검증 하 는 데 신뢰성 있 는 정 보 를 제공 해 야 한다.내 가 있 는 이곳 은 비어 있다.자신 은 자신의 상황 에 따라 적당 한 속성 을 초기 데이터 의 적재 용기 로 정의 합 니 다.
    2.CommonAuthorizeHandler:AuthorizationHandler이것 이 중점 이 고 검 증 된 논리 연산 을 탑재 합 니 다.
    override Task Handle Requirement Async 방법 을 다시 써 야 합 니 다.모든 논 리 는 이 방법 에 있 습 니 다.그의 주요 논 리 는 위의 사용자 정의 미들웨어 와 비슷 하고 위의 첫 번 째 단계 만 적 습 니 다.인증 절 차 는 다음 과 같 습 니 다.
  • 현재 http 머리 에 지 니 고 있 는 jwt(머리 에 저 장 된 Authorization)가 져 오기;
  • 은 앞에서 말 한 TokenContext 를 사용 하여 필요 한 검증 과 사용자 정의 복잡 한 검증 을 합 니 다.
  • 현재 방문 한 사용자 정 보 를 얻 습 니 다.저 희 는 사용자 의 기본 정 보 를 payLoad["ruser"에 두 었 습 니 다.코드 가
  • 을 어떻게 조작 하 는 지 보 세 요.
  • 은 지금까지 인증 을 한 것 으로 당신 이 신분 이 있 는 사람 임 을 나타 낸다.다음은 권한 검증 을 하 는 것 입 니 다.당신 은 신분 이 있 는 사람 입 니 다.당신 이 아무 데 나 방문 하 는 사람 이 아니 라 는 것 을 의미 합 니 다.어떤 url 이나 action 에 접근 할 수 있 으 면 권한 검증 을 받 아야 합 니 다
  • 저 희 는 권한 검증 을 userContext.Authorize 방법 에 넣 습 니 다.(여기 서 어떻게 조작 하 는 지 깊이 설명 하지 않 습 니 다.기본 원 리 는 데이터 베이스 나 캐 시 에서 현재 사용자 가 대응 하 는 권한 목록,즉 url 목록 을 가 져 와 비교 하 는 것 입 니 다)
    context.Succeed(requirement);인증 이 성공 한 것 입 니 다.이것 이 없 으 면 기본 인증 이 실 패 했 습 니 다.
    UserContext 는 권한 검증 을 맡 았 기 때문에 절 차 를 복잡 하 게 만 들 지 않 고 다시 사용 할 수 있 으 며 그런 형식 으로 검증 하 는 것 도
  • 으로 전환 하기 쉽다.
    3.간단 하지 않 습 니까?사용자 정의 파이프 검증 코드 와 거의 똑 같 습 니 다.
    사용자 정의 정책 을 어떻게 사용 합 니까?
    1.startup 클래스 의 Configure Services 에 다음 코드 를 추가 합 니 다.
    
    services.AddAuthorization(option =>
       {
        
    
        #region        
        option.AddPolicy("common", policy => policy.Requirements.Add(new CommonAuthorize()));
        #endregion
    
    
       }).AddAuthentication(option =>
       {
        option.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
       }).AddJwtBearer(option =>
       {
        if (!string.IsNullOrEmpty(config["JwtOption:SecurityKey"]))
        {
         TokenContext.securityKey = config["JwtOption:SecurityKey"];
        }
        //         
        option.TokenValidationParameters = new TokenValidationParameters
        {
         
         IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(TokenContext.securityKey))//  SecurityKey
        };
       });
    
       //     IOC  
       
       services.AddSingleton<IAuthorizationHandler, CommonAuthorizeHandler>();
         이상 코드 는 주로 세 부분 으로 나 뉜 다.
         1.위 에서 사용자 정의 정책 을 추가 하고 이름 을 짓 기;
         2.비밀 키 를 설정 합 니 다.이 비밀 키 는 바로 이전 절 에서 jwt 를 생 성 하 는 비밀 키 입 니 다.똑 같이 해 야 합 니 다.그렇지 않 으 면 서명 이 정확 하지 않 습 니 다.
         3.위 코드 와 같은 중요 한 종류의 CommonAuthorizeHandler 를 주입 합 니 다.
    2.startup 클래스 의 Configure 에 app.UseAuthentication()을 추가 합 니 다.
    3.검증 이 필요 한 Controller 또는 Action 에[Authorize(Policy="common")]속성 을 추가 하고 다음 그림 을 보십시오.
    여기까지 사용자 정의 정책 검증 을 사용 할 수 있 습 니 다.
     
    파이프 와 사용자 정의 정책 두 가지 형식 으로 검증 하 는 것 은 어떤 차이 가 있 습 니까?
    효과 적 으로 보면 다 똑 같 아 요.조금 달라 요.
  • 파 이 프 를 사용 하 는 방식 으로 편리 함 을 느끼 고 선명 함
  • 사용자 정의 정책 을 사용 하 는 방식 은 효율 이 약간 높 습 니 다.모든 요청 이 익명 으로 접근 할 수 있 는 연산 과 파 이 프 를 만 드 는 소 모 를 하 는 것 이 아니 라 Authorize 속성 을 가 진 Controller 와 Action 만 들 어 갈 수 있 습 니 다.물론 이 손실 은 무시 하고 자신의 취향 을 볼 수 있다.
  • 네가 그런 것 을 좋아 하 는 지 에 대해 서 는 어떤 것 을 사용 하 든 성능 은 무시 해도 된다.
    어떤 방식 으로 jwt 를 신분 과 권한 검증 으로 사용 하 든 간단 하지 않 습 니까?관건 은 여기 서도 권한 검증 의 논 리 를 추출 하면 코드 가 더욱 명확 해 집 니 다.
    Authorize 의 속성 형식 에 대해 다른 전략 도 많이 있 습 니 다.예 를 들 어 사용자,설명,캐릭터 등 은 홈 페이지 https://docs.microsoft.com/zh-cn/aspnet/core/security/authorization/?view=aspnetcore-2.0 을 볼 수 있 습 니 다.
    다음 장 에 서 는 사용자,설명,역할 검증,그리고 사용자 정의 검증 에서 어떻게 이 루어 지 는 지 설명 하여 사람들 이 그 에 대해 명확 한 대 비 를 할 수 있 도록 할 것 이다.
    총결산
    이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

    좋은 웹페이지 즐겨찾기