ASP.NET Core 는 사용자 정의 인증 속성 제어 접근 권한 을 사용 합 니 다.

머리말
응용 프로그램 에서 우 리 는 방문 한 클 라 이언 트 에 대해 유효성 검증 을 해 야 한 다 는 것 을 잘 알 고 있 습 니 다.유효한 증빙(AccessToken)을 제공 하 는 터미널 응용 프로그램 만 우리 의 제어 사이트(예 를 들 어 WebAPI 사이트)를 방문 할 수 있 습 니 다.이때 우 리 는 속성 을 검증 하 는 방법 으로 해결 할 수 있 습 니 다.
본 고 는 ASP.NET Core 가 사용자 정의 인증 속성 을 사용 하여 접근 권한 을 제어 하 는 것 과 관련 된 내용 을 상세 하 게 소개 하고 참고 학습 을 제공 할 것 입 니 다.다음은 더 이상 할 말 이 없 으 니 상세 한 소 개 를 해 보 겠 습 니 다.
방법 은 아래 와 같다.
1.Public class Startup 설정:

//      (        )
services.AddCors(options =>
{
options.AddPolicy("AllowOriginOtherBis",
builder => builder.WithOrigins("https://1.16.9.12:4432", "https://pc12.ato.biz:4432", "https://localhost:44384", "https://1.16.9.12:4432", "https://pc12.ato.biz:4432").AllowAnyMethod().AllowAnyHeader());
});

//              Action  [TerminalApp()]  。

services.AddSingleton<IAuthorizationHandler, TerminalAppAuthorizationHandler>();
services.AddAuthorization(options =>
{
options.AddPolicy("TerminalApp", policyBuilder =>
{
policyBuilder.Requirements.Add(new TerminalAppAuthorizationRequirement());
});
});
2.Public void Configure(IApplicationBuilder app,IHosting Environment env)의 설정:

app.UseHttpsRedirection();  //  Https  
app.UseCors("AllowOriginOtherBis"); //          
3.예시 WebApi 프로젝트 구조:
 
4.주요 코드(내 가 사용 한 데이터베이스 에서 검증):

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
 internal class TerminalAppAttribute : AuthorizeAttribute
 {
  public string AppID { get; }

  /// <summary>
  ///        API
  /// </summary>
  /// <param name="appID"></param>
  public TerminalAppAttribute(string appID="") : base("TerminalApp")
  {
   AppID = appID;
  }
 }

public abstract class AttributeAuthorizationHandler<TRequirement, TAttribute> : AuthorizationHandler<TRequirement> where TRequirement : IAuthorizationRequirement where TAttribute : Attribute
 {
  protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement)
  {
   var attributes = new List<TAttribute>();

   if ((context.Resource as AuthorizationFilterContext)?.ActionDescriptor is ControllerActionDescriptor action)
   {
    attributes.AddRange(GetAttributes(action.ControllerTypeInfo.UnderlyingSystemType));
    attributes.AddRange(GetAttributes(action.MethodInfo));
   }

   return HandleRequirementAsync(context, requirement, attributes);
  }

  protected abstract Task HandleRequirementAsync(AuthorizationHandlerContext context, TRequirement requirement, IEnumerable<TAttribute> attributes);

  private static IEnumerable<TAttribute> GetAttributes(MemberInfo memberInfo)
  {
   return memberInfo.GetCustomAttributes(typeof(TAttribute), false).Cast<TAttribute>();
  }
 }

 internal class TerminalAppAuthorizationHandler : AttributeAuthorizationHandler<TerminalAppAuthorizationRequirement,TerminalAppAttribute>
 {
  protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, TerminalAppAuthorizationRequirement requirement, IEnumerable<TerminalAppAttribute> attributes)
  {
   object errorMsg = string.Empty;
   //           ,         ,      403
   if (context.Resource is AuthorizationFilterContext filterContext &&
filterContext.ActionDescriptor is ControllerActionDescriptor descriptor)
   {
    //          ,
    if (descriptor != null)
    {
     var actionAttributes = descriptor.MethodInfo.GetCustomAttributes(inherit: true);
     bool isAnonymous = actionAttributes.Any(a => a is AllowAnonymousAttribute);
     //      ,     accesstoken 
     if (isAnonymous)
     {
      context.Succeed(requirement);
      return Task.CompletedTask;
     }
     else
     {
      //url  access_token
      // AuthorizationHandlerContext  HttpContext,        
      var httpContext = (context.Resource as AuthorizationFilterContext).HttpContext;
      //var questUrl = httpContext.Request.Path.Value.ToLower();
      string requestAppID = httpContext.Request.Headers["appid"];
      string requestAccessToken = httpContext.Request.Headers["access_token"];
      if ((!string.IsNullOrEmpty(requestAppID)) && (!string.IsNullOrEmpty(requestAccessToken)))
      {
       if (attributes != null)
       {
        //          AppID                  
        if (attributes.ToArray().ToString()=="") 
        {
         //            App     ,        APPID   ID    
         bool mat = false;
         foreach (var terminalAppAttribute in attributes)
         {
          if (terminalAppAttribute.AppID == requestAppID)
          {
           mat = true;
           break;
          }
         }
         if (!mat)
         {
          errorMsg = ReturnStd.NotAuthorize("                       .");
          return HandleBlockedAsync(context, requirement, errorMsg);
         }
        }
       }

       //     attributes,                  ,             ID         
       string valRst = ValidateToken(requestAppID, requestAccessToken);
       if (string.IsNullOrEmpty(valRst))
       {
        context.Succeed(requirement);
        return Task.CompletedTask;
       }
       else
       {
        errorMsg = ReturnStd.NotAuthorize("AccessToken    (" + valRst + ")","91");
        return HandleBlockedAsync(context, requirement, errorMsg);
       }
      }
      else
      {
       errorMsg = ReturnStd.NotAuthorize("   AppID Token."); 
       return HandleBlockedAsync(context, requirement, errorMsg);
       //return Task.CompletedTask;
      }
     }
    }
   }
   else
   {
    errorMsg = ReturnStd.NotAuthorize("FilterContext     .");
    return HandleBlockedAsync(context, requirement, errorMsg);
   }

   errorMsg = ReturnStd.NotAuthorize("    .");
   return HandleBlockedAsync(context,requirement, errorMsg);
  }


  //    (       )
  /// <summary>
  ///            AccessToken    
  /// </summary>
  /// <param name="appID">  APP ID</param>
  /// <param name="accessToken">  APP     AppKEY     AccessToken,           </param>
  /// <returns></returns>
  private string ValidateToken(string appID,string accessToken)
  {
   try
   {
    DBContextMain dBContext = new DBContextMain();
    string appKeyOnServer = string.Empty;
    //      AppID   KEY( KEY       AES_KEY
    AuthApp authApp = dBContext.AuthApps.FirstOrDefault(a => a.AppID == appID);
    if (authApp == null)
    {
     return "            !";
    }
    else
    {
     appKeyOnServer = authApp.APPKey;
    }
    if (string.IsNullOrEmpty(appKeyOnServer))
    {
     return "           !"; 
    }

    string tmpToken = string.Empty;
    tmpToken = System.Net.WebUtility.UrlDecode(accessToken);//     Token     (       +=     ,       )
    tmpToken = OCrypto.AES16Decrypt(tmpToken, appKeyOnServer); //  APPKEY     

    if (string.IsNullOrEmpty(tmpToken))
    {
     return "              !";
    }
    else
    {
     try
     {
      //      im_cloud_sv001-appid-ticks  
      //    ,        ,  10      
      long tmpTime =Convert.ToInt64(tmpToken.Substring(tmpToken.LastIndexOf("-")+1));
      //DateTime dt = DateTime.ParseExact(tmpTime, "yyyyMMddHHmmss", CultureInfo.CurrentCulture);
      DateTime dt= new DateTime(tmpTime);
      bool IsInTimeSpan = (Convert.ToDouble(ODateTime.DateDiffSeconds(dt, DateTime.Now)) <= 7200);
      bool IsInternalApp = (tmpToken.IndexOf("im_cloud_sv001-") >= 0);
      if (!IsInternalApp || !IsInTimeSpan)
      {
       return "           !";
      }
      else
      {
       return string.Empty; //    
      }
     }
     catch (Exception ex)
     {
      return "      (" + ex.Message + ")";
     }

    }
   }
   catch (Exception ex)
   {
    return "      (" + ex.Message + ")";
   }
  }

  private Task HandleBlockedAsync(AuthorizationHandlerContext context, TerminalAppAuthorizationRequirement requirement, object errorMsg)
  {
   var authorizationFilterContext = context.Resource as AuthorizationFilterContext;
   authorizationFilterContext.Result = new JsonResult(errorMsg) { StatusCode = 202 };
   //   403          ,  Accepted202,      
   context.Succeed(requirement);
   return Task.CompletedTask;
  }
 }

 internal class TerminalAppAuthorizationRequirement : IAuthorizationRequirement
 {
  public TerminalAppAuthorizationRequirement()
  {
  }
 }
5.해당 Token 인증 코드:

[AutoValidateAntiforgeryToken] //                
 [Route("api/get_accesstoken")]
 public class GetAccessTokenController : Controller
 {
  //        
  //  {"access_token":"ACCESS_TOKEN","expires_in":7200}    2   
  //     {"errcode":40013,"errmsg":"invalid appid"}
  [AllowAnonymous]
  public ActionResult<string> Get()
  {
   try
   {
    string tmpToken = string.Empty;

    string appID = HttpContext.Request.Headers["appid"];
    string appKey = HttpContext.Request.Headers["appkey"];

    if ((appID.Length < 5) || appKey.Length != 32)
    {
     return "{'errcode':10000,'errmsg':'appid appkey   '}";
    }
    //token  im_cloud_sv001-appid-ticks  
    long timeTk = DateTime.Now.Ticks; //     :633603924670937500
             //DateTime dt = new DateTime(timeTk);//      

    string plToken = "im_cloud1-" + appID + "-" + timeTk;
    tmpToken = OCrypto.AES16Encrypt(plToken, appKey); //  APPKEY  

    tmpToken = System.Net.WebUtility.UrlEncode(tmpToken);
    //     Token(       +=     ,       )
    tmpToken = "{'access_token':'" + tmpToken + "','expires_in':7200}";
    return tmpToken;
   }
   catch (Exception ex)
   {
    return "{'errcode':10001,'errmsg':'" + ex.Message +"'}";
   }
  }
 }

GetAccessTokenController.cs
6.이렇게 해서 우리 가 통제 해 야 하 는 곳 에[TerminalApp()]을 추가 하면 된다.그러면 모든 권한 을 수 여 받 은 App 이 방문 할 수 있다.물론[TerminalApp('app 01')]을 사용 하여 특정한 ID 를 app 01 로 제한 하 는 응용 프로그램 방문 도 할 수 있다.

 [Area("SYS")]  //   : api/sys/user
 [Produces("application/json")]
 [TerminalApp()] 
 public class UserController : Controller
{
//
}
 7.CS 클 라 이언 트 가 웹 API 를 통 해 데이터 호출 예 시 를 업로드 합 니 다.

string postURL = "http://sv12.ato.com/api/sys/user/postnew";
 
Dictionary<string, string> headerDic2 = new Dictionary<string, string>
{
 { "appid", MainFramework.CloudAppID },
 { "access_token", accessToken }
};
string pushRst = OPWeb.Post(postURL, headerDic2, "POST", sYS_Users);
if (string.IsNullOrEmpty(pushRst))
{
 MyMsg.Information("    !");
}
else
{
 MyMsg.Information("    !", pushRst);
}

string accessToken = MainFramework.CloudAccessToken;
if (accessToken.IndexOf("ERROR:") >= 0)
{
 MyMsg.Information("  Token  :" + accessToken);
 return;
}
총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

좋은 웹페이지 즐겨찾기