다음을 통해 공유


안전한 .NET 마이크로 서비스 및 웹 애플리케이션 만들기

팁 (조언)

이 콘텐츠는 .NET Docs 또는 오프라인으로 읽을 수 있는 다운로드 가능한 무료 PDF로 제공되는 컨테이너화된 .NET 애플리케이션용 .NET 마이크로 서비스 아키텍처인 eBook에서 발췌한 내용입니다.

컨테이너화된 .NET 애플리케이션을 위한 .NET 마이크로서비스 아키텍처 eBook의 표지 썸네일.

마이크로 서비스 및 웹 애플리케이션의 보안에 대한 많은 측면이 있으므로 이 항목은 이와 같은 여러 책을 쉽게 읽어들일 수 있습니다. 따라서 이 섹션에서는 인증, 권한 부여 및 애플리케이션 비밀에 집중합니다.

.NET 마이크로 서비스 및 웹 애플리케이션에서 인증 구현

서비스에서 게시한 리소스 및 API를 신뢰할 수 있는 특정 사용자 또는 클라이언트로 제한해야 하는 경우가 많습니다. 이러한 종류의 API 수준 신뢰 결정을 내리는 첫 번째 단계는 인증입니다. 인증은 사용자의 ID를 안정적으로 확인하는 프로세스입니다.

마이크로 서비스 시나리오에서 일반적으로 인증은 중앙에서 처리됩니다. API 게이트웨이를 사용하는 경우 게이트웨이는 그림 9-1과 같이 인증하기에 좋은 장소입니다. 이 방법을 사용하는 경우 게이트웨이에서 온 메시지인지 여부에 관계없이 메시지를 인증하기 위한 추가 보안이 마련되지 않은 한 개별 마이크로 서비스에 직접 연결할 수 없는지 확인합니다(API 게이트웨이 제외).

클라이언트 모바일 앱이 백 엔드와 상호 작용하는 방법을 보여 주는 다이어그램

그림 9-1. API 게이트웨이를 사용한 중앙 집중식 인증

API 게이트웨이는 인증을 중앙 집중화할 때 마이크로 서비스에 요청을 전달할 때 사용자 정보를 추가합니다. 서비스에 직접 액세스할 수 있는 경우 Azure Active Directory와 같은 인증 서비스 또는 STS(보안 토큰 서비스) 역할을 하는 전용 인증 마이크로 서비스를 사용하여 사용자를 인증할 수 있습니다. 신뢰 결정은 보안 토큰 또는 쿠키를 통해 서비스 간에 공유됩니다. (필요한 경우 쿠키 공유를 구현하여 ASP.NET Core 애플리케이션 간에 이러한 토큰을 공유할 수 있습니다.) 이 패턴은 그림 9-2에 설명되어 있습니다.

백 엔드 마이크로 서비스를 통한 인증을 보여 주는 다이어그램

그림 9-2. ID 마이크로 서비스에 의한 인증; 권한 부여 토큰을 사용하여 트러스트 공유

마이크로 서비스에 직접 액세스하는 경우 인증 및 권한 부여를 포함하는 신뢰는 마이크로 서비스 간에 공유되는 전용 마이크로 서비스에서 발급한 보안 토큰에 의해 처리됩니다.

ASP.NET 핵심 ID를 사용하여 인증

애플리케이션의 사용자를 식별하기 위한 ASP.NET Core의 기본 메커니즘은 ASP.NET Core Id 멤버 자격 시스템입니다. ASP.NET ID는 사용자 정보(로그인 정보, 역할 및 클레임 포함)를 개발자가 구성한 데이터 저장소에 저장합니다. 일반적으로 ASP.NET 핵심 ID 데이터 저장소는 패키지에 Microsoft.AspNetCore.Identity.EntityFrameworkCore 제공되는 Entity Framework 저장소입니다. 그러나 사용자 지정 저장소 또는 기타 타사 패키지를 사용하여 Azure Table Storage, CosmosDB 또는 기타 위치에 ID 정보를 저장할 수 있습니다.

팁 (조언)

ASP.NET Core 2.1 이상에서는 ASP.NET Core IDRazor 클래스 라이브러리로 제공하므로 이전 버전의 경우처럼 프로젝트에 필요한 코드가 많이 표시되지 않습니다. 요구 사항에 맞게 ID 코드를 사용자 지정하는 방법에 대한 자세한 내용은 ASP.NET Core 프로젝트의 스캐폴드 ID를 참조하세요.

다음 코드는 개별 사용자 계정 인증이 선택된 ASP.NET Core Web Application MVC 프로젝트 템플릿에서 가져옵니다. Program.cs 파일에서 Entity Framework Core를 사용하여 ASP.NET Core ID를 구성하는 방법을 보여 있습니다.

//...
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(
        builder.Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddDefaultIdentity<IdentityUser>(options =>
    options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();

builder.Services.AddRazorPages();
//...

ASP.NET Core Identity가 구성되면 서비스의 app.UseAuthentication() 파일에 다음 코드와 같이 추가하여 endpoints.MapRazorPages() 사용하도록 설정합니다.

//...
app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapRazorPages();
});
//...

중요합니다

ID가 제대로 작동하려면 앞의 코드 의 줄이 표시된 순서에 있어야 합니다 .

ASP.NET 핵심 ID를 사용하면 다음과 같은 여러 시나리오가 가능합니다.

  • UserManager 유형(userManager.CreateAsync)을 사용하여 새 사용자 정보를 만듭니다.

  • SignInManager 유형을 사용하여 사용자를 인증합니다. signInManager.SignInAsync를 사용하여 직접 로그인하거나, signInManager.PasswordSignInAsync를 사용하여 사용자의 암호가 올바른지 확인한 후 로그인할 수 있습니다.

  • 브라우저의 후속 요청에 로그인한 사용자의 ID 및 클레임이 포함되도록 쿠키에 저장된 정보(ASP.NET Core Identity 미들웨어에서 읽는 정보)를 기반으로 사용자를 식별합니다.

ASP.NET 핵심 ID는 2단계 인증도 지원합니다.

로컬 사용자 데이터 저장소를 사용하고 쿠키를 사용하는 요청 간에 ID를 유지하는 인증 시나리오의 경우(MVC 웹 애플리케이션의 경우처럼) ASP.NET Core Identity가 권장되는 솔루션입니다.

외부 공급자를 사용하여 인증

또한 ASP.NET Core는 외부 인증 공급자를 사용하여 사용자가 OAuth 2.0 흐름을 통해 로그인할 수 있도록 지원합니다. 즉, 사용자는 Microsoft, Google, Facebook 또는 Twitter와 같은 공급자의 기존 인증 프로세스를 사용하여 로그인하고 해당 ID를 애플리케이션의 ASP.NET Core ID와 연결할 수 있습니다.

외부 인증을 사용하려면, 앞에서 설명한 대로 인증 미들웨어를 포함하는 것 외에도, 다음 예제와 같이 app.UseAuthentication()에 외부 공급자를 등록해야 합니다.

//...
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

services.AddAuthentication()
    .AddMicrosoftAccount(microsoftOptions =>
    {
        microsoftOptions.ClientId = builder.Configuration["Authentication:Microsoft:ClientId"];
        microsoftOptions.ClientSecret = builder.Configuration["Authentication:Microsoft:ClientSecret"];
    })
    .AddGoogle(googleOptions => { ... })
    .AddTwitter(twitterOptions => { ... })
    .AddFacebook(facebookOptions => { ... });
//...

인기 있는 외부 인증 공급자 및 관련 NuGet 패키지는 다음 표에 나와 있습니다.

공급자 패키지
마이크로소프트 Microsoft.AspNetCore.Authentication.MicrosoftAccount
구글 Microsoft.AspNetCore.Authentication.Google
Facebook Microsoft.AspNetCore.Authentication.Facebook
트위터 Microsoft.AspNetCore.Authentication.Twitter

모든 경우에 공급업체 종속적이고 일반적으로 다음과 같은 애플리케이션 등록 절차를 완료해야 합니다.

  1. 클라이언트 애플리케이션 ID 가져오기
  2. 클라이언트 애플리케이션 암호를 가져옵니다.
  3. 권한 부여 미들웨어 및 등록된 공급자가 처리하는 리디렉션 URL 구성
  4. 필요에 따라 SSO(Single Sign On) 시나리오에서 로그아웃을 제대로 처리하도록 로그아웃 URL을 구성합니다.

외부 공급자에 대한 앱을 구성하는 방법에 대한 자세한 내용은 ASP.NET Core 설명서)의 외부 공급자 인증을 참조하세요.

팁 (조언)

모든 세부 정보는 이전에 언급한 권한 부여 미들웨어 및 서비스에 의해 처리됩니다. 따라서 앞에서 언급한 인증 공급자를 등록하는 것 외에 그림 9-3과 같이 Visual Studio에서 ASP.NET Core 웹 애플리케이션 프로젝트를 만들 때 개별 사용자 계정 인증 옵션을 선택하기만 하면 됩니다.

새 ASP.NET Core 웹 애플리케이션 대화 상자의 스크린샷

그림 9-3. Visual Studio 2019에서 웹 애플리케이션 프로젝트를 만들 때 외부 인증을 사용하기 위한 개별 사용자 계정 옵션을 선택합니다.

이전에 나열된 외부 인증 공급자 외에도 더 많은 외부 인증 공급자를 사용하기 위한 미들웨어를 제공하는 타사 패키지를 사용할 수 있습니다. 목록은 GitHub의 AspNet.Security.OAuth.Providers 리포지토리를 참조하세요.

고유한 외부 인증 미들웨어를 만들어 특별한 요구 사항을 해결할 수도 있습니다.

전달자 토큰으로 인증

ASP.NET 핵심 ID(또는 ID 및 외부 인증 공급자)를 사용하여 인증하는 것은 쿠키에 사용자 정보를 저장하는 것이 적절한 많은 웹 애플리케이션 시나리오에 적합합니다. 그러나 다른 시나리오에서는 쿠키가 데이터를 유지 및 전송하는 자연스러운 수단이 아닙니다.

예를 들어 SPA(단일 페이지 애플리케이션), 네이티브 클라이언트 또는 다른 Web API에서 액세스할 수 있는 RESTful 엔드포인트를 노출하는 ASP.NET Core Web API에서는 일반적으로 전달자 토큰 인증을 대신 사용하려고 합니다. 이러한 유형의 애플리케이션은 쿠키에서 작동하지 않지만 전달자 토큰을 쉽게 검색하여 후속 요청의 권한 부여 헤더에 포함할 수 있습니다. 토큰 인증을 사용하도록 설정하기 위해 ASP.NET Core 는 OAuth 2.0OpenID Connect를 사용하기 위한 몇 가지 옵션을 지원합니다.

OpenID Connect 또는 OAuth 2.0 ID 공급자를 사용하여 인증

사용자 정보가 Azure Active Directory 또는 OpenID Connect 또는 OAuth 2.0을 지원하는 다른 ID 솔루션에 저장된 경우 Microsoft.AspNetCore.Authentication.OpenIdConnect 패키지를 사용하여 OpenID Connect 워크플로를 사용하여 인증할 수 있습니다. 예를 들어 eShopOnContainers에서 Identity.Api 마이크로 서비스에 인증하기 위해 ASP.NET Core 웹 애플리케이션은 Program.cs 다음 간소화된 예제와 같이 해당 패키지의 미들웨어를 사용할 수 있습니다.

// Program.cs

var identityUrl = builder.Configuration.GetValue<string>("IdentityUrl");
var callBackUrl = builder.Configuration.GetValue<string>("CallBackUrl");
var sessionCookieLifetime = builder.Configuration.GetValue("SessionCookieLifetimeMinutes", 60);

// Add Authentication services

services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddCookie(setup => setup.ExpireTimeSpan = TimeSpan.FromMinutes(sessionCookieLifetime))
.AddOpenIdConnect(options =>
{
    options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.Authority = identityUrl.ToString();
    options.SignedOutRedirectUri = callBackUrl.ToString();
    options.ClientId = useLoadTest ? "mvctest" : "mvc";
    options.ClientSecret = "secret";
    options.ResponseType = useLoadTest ? "code id_token token" : "code id_token";
    options.SaveTokens = true;
    options.GetClaimsFromUserInfoEndpoint = true;
    options.RequireHttpsMetadata = false;
    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("orders");
    options.Scope.Add("basket");
    options.Scope.Add("marketing");
    options.Scope.Add("locations");
    options.Scope.Add("webshoppingagg");
    options.Scope.Add("orders.signalrhub");
});

// Build the app
//…
app.UseAuthentication();
//…
app.UseEndpoints(endpoints =>
{
    //...
});

이 워크플로를 사용하는 경우 모든 사용자 정보 스토리지 및 인증이 ID 서비스에서 처리되므로 ASP.NET 핵심 ID 미들웨어가 필요하지 않습니다.

ASP.NET Core 서비스에서 보안 토큰 발급

외부 ID 공급자를 사용하는 대신 로컬 ASP.NET Core Identity 사용자에 대한 보안 토큰을 발급하려는 경우 몇 가지 좋은 타사 라이브러리를 활용할 수 있습니다.

IdentityServer4OpenIddict 는 ASP.NET Core 서비스에서 보안 토큰을 발급할 수 있도록 ASP.NET 핵심 ID와 쉽게 통합되는 OpenID Connect 공급자입니다. IdentityServer4 설명서에는 라이브러리 사용에 대한 자세한 지침이 있습니다. 그러나 IdentityServer4를 사용하여 토큰을 발급하는 기본 단계는 다음과 같습니다.

  1. Program.cs 작성기를 호출하여 IdentityServer4를 구성합니다. Services.AddIdentityServer.

  2. 앱을 호출합니다. Program.cs UseIdentityServer를 사용하여 애플리케이션의 HTTP 요청 처리 파이프라인에 IdentityServer4를 추가합니다. 이렇게 하면 라이브러리가 /connect/token과 같은 OpenID Connect 및 OAuth2 엔드포인트에 대한 요청을 제공할 수 있습니다.

  3. 다음 데이터를 설정하여 ID 서버를 구성합니다.

    • 서명에 사용할 자격 증명 입니다.

    • 사용자가 액세스를 요청할 수 있는 ID 및 API 리소스 :

      • API 리소스는 사용자가 액세스 토큰을 사용하여 액세스할 수 있는 보호된 데이터 또는 기능을 나타냅니다. API 리소스의 예로는 권한 부여가 필요한 웹 API(또는 API 집합)가 있습니다.

      • ID 리소스는 사용자를 식별하기 위해 클라이언트에 제공되는 정보(클레임)를 나타냅니다. 클레임에는 사용자 이름, 전자 메일 주소 등이 포함될 수 있습니다.

    • 특정한 클라이언트들이 토큰을 요청하기 위해 연결할 것입니다.

    • ASP.NET Core Identity 또는 대안과 같은 사용자 정보에 대한 스토리지 메커니즘입니다.

IdentityServer4에서 사용할 클라이언트 및 리소스를 지정하는 경우 메모리 내 클라이언트 또는 리소스 저장소를 사용하는 메서드에 적절한 형식의 컬렉션을 전달할 IEnumerable<T> 수 있습니다. 또는 더 복잡한 시나리오의 경우 종속성 주입을 통해 클라이언트 또는 리소스 공급자 유형을 제공할 수 있습니다.

사용자 지정 IClientStore 형식에서 제공하는 메모리 내 리소스 및 클라이언트를 사용하는 IdentityServer4의 샘플 구성은 다음 예제와 같습니다.

// Program.cs

builder.Services.AddSingleton<IClientStore, CustomClientStore>();
builder.Services.AddIdentityServer()
    .AddSigningCredential("CN=sts")
    .AddInMemoryApiResources(MyApiResourceProvider.GetAllResources())
    .AddAspNetIdentity<ApplicationUser>();
//...

보안 토큰 사용

OpenID Connect 엔드포인트에 대해 인증하거나 자체 보안 토큰을 발급하는 것이 몇 가지 시나리오를 해결합니다. 하지만 다른 서비스에서 제공한 유효한 보안 토큰이 있는 사용자에 대한 액세스를 제한해야 하는 서비스는 어떨까요?

이 시나리오의 경우 JWT 토큰을 처리하는 인증 미들웨어는 Microsoft.AspNetCore.Authentication.JwtBearer 패키지에서 사용할 수 있습니다. JWT는 "JSON 웹 토큰"을 의미하며 보안 클레임을 전달하기 위한 일반적인 보안 토큰 형식(RFC 7519에서 정의됨)입니다. 미들웨어를 사용하여 이러한 토큰을 사용하는 방법의 간소화된 예제는 eShopOnContainers의 Ordering.Api 마이크로 서비스에서 가져온 이 코드 조각처럼 보일 수 있습니다.

// Program.cs

var identityUrl = builder.Configuration.GetValue<string>("IdentityUrl");

// Add Authentication services

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme;

}).AddJwtBearer(options =>
{
    options.Authority = identityUrl;
    options.RequireHttpsMetadata = false;
    options.Audience = "orders";
});

// Build the app

app.UseAuthentication();
//…
app.UseEndpoints(endpoints =>
{
    //...
});

이 사용의 매개 변수는 다음과 같습니다.

  • Audience 는 들어오는 토큰의 수신자 또는 토큰이 액세스 권한을 부여하는 리소스를 나타냅니다. 이 매개 변수에 지정된 값이 토큰의 매개 변수와 일치하지 않으면 토큰이 거부됩니다.

  • Authority 는 토큰 발급 인증 서버의 주소입니다. JWT 전달자 인증 미들웨어는 이 URI를 사용하여 토큰 서명의 유효성을 검사하는 데 사용할 수 있는 공개 키를 가져옵니다. 또한 미들웨어는 토큰의 매개 변수가 iss 이 URI와 일치하는지 확인합니다.

또 다른 매개 변수 RequireHttpsMetadata는 테스트 용도로 유용합니다. 인증서가 없는 환경에서 테스트할 수 있도록 이 매개 변수를 false로 설정합니다. 실제 배포에서 JWT 전달자 토큰은 항상 HTTPS를 통해서만 전달되어야 합니다.

이 미들웨어를 사용하면 JWT 토큰이 권한 부여 헤더에서 자동으로 추출됩니다. 그런 다음 역직렬화되고, AudienceAuthority 매개 변수의 값을 사용하여 유효성이 검사된 후, 나중에 MVC 작업 또는 권한 부여 필터에서 참조할 사용자 정보로 저장됩니다.

JWT 전달자 인증 미들웨어는 권한을 사용할 수 없는 경우 로컬 인증서를 사용하여 토큰의 유효성을 검사하는 등 고급 시나리오를 지원할 수도 있습니다. 이 시나리오에서는 TokenValidationParameters 개체 안에 JwtBearerOptions 개체를 지정할 수 있습니다.

추가 리소스