다음을 통해 공유


인증 라이브러리를 사용하여 ASP.NET Core Blazor WebAssembly 독립 실행형 앱 보호

참고 항목

이 문서의 최신 버전은 아닙니다. 현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

Warning

이 버전의 ASP.NET Core는 더 이상 지원되지 않습니다. 자세한 내용은 .NET 및 .NET Core 지원 정책을 참조 하세요. 현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

Important

이 정보는 상업적으로 출시되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적, 또는 묵시적인 보증을 하지 않습니다.

현재 릴리스는 이 문서의 .NET 8 버전을 참조 하세요.

이 문서에서는 Blazor WebAssembly 인증 라이브러리를 사용하여 ASP.NET Core Blazor WebAssembly 독립 실행형 앱을 보호하는 방법을 설명합니다.

인증 라이브러리()는 Blazor WebAssembly MSALmsal.js(Authentication.jsMicrosoft 인증 라이브러리)을 통해 PKCE(코드 교환용 증명 키) 권한 부여 코드 흐름만 지원합니다. 다른 권한 부여 흐름을 구현하려면 MSAL 지침에 액세스하여 MSAL을 직접 구현하지만 앱에 PKCE Blazor 이외의 권한 부여 흐름은 지원하거나 사용하지 않는 것이 좋습니다.

Microsoft Entra(ME-ID) 및 AAD B2C(Azure Active Directory B2C) 지침의 경우 이 항목의 지침을 따르지 마세요. Microsoft Entra ID를 사용하여 ASP.NET Core Blazor WebAssembly 독립 실행형 앱 보안 또는 Azure Active Directory B2C를 사용하여 ASP.NET Core Blazor WebAssembly 독립 실행형 앱 보호 참조

이 문서를 읽은 후 추가 보안 시나리오에 대한 자세한 내용은 ASP.NET Core Blazor WebAssembly 추가 보안 시나리오를 참조하세요.

연습

연습의 하위 섹션에서는 다음 방법을 설명합니다.

  • 앱 등록
  • Blazor 앱 만들기
  • 앱 실행

앱 등록

IP의 유지 관리자가 제공한 지침에 따라 OIDC(OpenID Connect)Identity 공급자(IP)에 앱을 등록합니다.

다음과 같은 정보를 기록해 둡니다.

  • 기관(예: https://accounts.google.com/).
  • 애플리케이션(클라이언트) ID(예: 2...7-e...q.apps.googleusercontent.com).
  • 추가 IP 구성(IP 설명서 참조).

참고 항목

IP는 OIDC를 사용해야 합니다. 예를 들어, Facebook의 IP는 OIDC 규격 공급자가 아니므로 Facebook IP에는 이 항목의 지침이 적용되지 않습니다. 자세한 내용은 보안 ASP.NET Core Blazor WebAssembly를 참조하세요.

Blazor 앱 만들기

라이브러리를 사용하는 Microsoft.AspNetCore.Components.WebAssembly.Authentication 독립 실행형 Blazor WebAssembly 앱을 만들려면 선택한 도구에 대한 지침을 따르세요. 인증 에 대한 지원을 추가하는 경우 앱 설정 및 구성에 대한 지침은 이 문서의 앱 부분 섹션을 참조하세요.

인증 메커니즘을 사용하여 새 Blazor WebAssembly 프로젝트를 만들려면

앱 템플릿을 Blazor WebAssembly 선택한 후 인증 유형을 개별 계정으로 설정합니다.

앱 템플릿을 Blazor WebAssembly 선택한 후 인증 유형을 개별 계정으로 설정합니다. ASP.NET Core Hosted 확인란이 선택되어 있지 않은지 확인합니다.

개별 계정 선택은 ASP.NET Core의 Identity 시스템을 사용합니다. 이렇게 선택하면 인증 지원이 추가되고 사용자가 데이터베이스에 저장되지 않습니다. 이 문서의 다음 섹션에서는 추가 세부 정보를 제공합니다.

앱 구성

IP의 지침에 따라 앱을 구성합니다. 최소한 앱에는 앱 파일의 Local:Authority wwwroot/appsettings.json 구성 설정과 Local:ClientId 구성이 필요합니다.

{
  "Local": {
    "Authority": "{AUTHORITY}",
    "ClientId": "{CLIENT ID}"
  }
}

포트 5001의 주소에서 실행되는 localhost 앱에 대한 Google OAuth 2.0 OIDC 예제:

{
  "Local": {
    "Authority": "https://accounts.google.com/",
    "ClientId": "2...7-e...q.apps.googleusercontent.com",
    "PostLogoutRedirectUri": "https://localhost:5001/authentication/logout-callback",
    "RedirectUri": "https://localhost:5001/authentication/login-callback",
    "ResponseType": "code"
  }
}

리디렉션 URI(https://localhost:5001/authentication/login-callback)는 자격 증명>{NAME}>권한 있는 리디렉션 URIGoogle API 콘솔에 등록됩니다. 여기서 {NAME}은 Google API 콘솔의 OAuth 2.0 클라이언트 ID 앱 목록에 있는 앱의 클라이언트 이름입니다.

참고 항목

OAuth 2.0 사양에 따라 일부 OIDC IP에는 리디렉션 URI에 대한 포트 번호를 localhost 제공할 필요가 없습니다. 일부 IP는 루프백 주소에 대한 리디렉션 URI가 포트를 생략하도록 허용합니다. 다른 포트 번호(예 *: )에 와일드카드를 사용할 수 있습니다. 자세한 내용은 IP 설명서를 참조하세요.

앱 실행

다음 방법 중 하나를 사용하여 앱을 실행합니다.

  • Visual Studio
    • 실행 단추를 선택합니다.
    • 메뉴에서 디버그>디버깅 시작을 사용합니다.
    • F5키를 누릅니다.
  • .NET CLI 명령 셸: 앱의 dotnet watch 폴더에서 (또는 dotnet run) 명령을 실행합니다.

앱의 일부

이 섹션에서는 프로젝트 템플릿에서 Blazor WebAssembly 생성된 앱의 부분과 앱이 구성된 방법에 대해 설명합니다. 연습 섹션의 지침을 사용하여 앱을 만든 경우 기본 작업 애플리케이션에 대해 이 섹션에서 따라야 할 구체적인 지침은 없습니다. 이 섹션의 지침은 사용자를 인증하고 권한을 부여하도록 앱을 업데이트하는 데 유용합니다. 그러나 앱을 업데이트하는 다른 방법은 연습 섹션의 지침에서 새 앱을 만들고 앱의 구성 요소, 클래스 및 리소스를 새 앱으로 이동하는 것입니다.

인증 패키지

앱이 개별 사용자 계정을 사용하도록 만들어진 경우 해당 앱은 자동으로 Microsoft.AspNetCore.Components.WebAssembly.Authentication 패키지에 대한 패키지 참조를 받습니다. 패키지는 앱이 사용자를 인증하고 보호된 API를 호출하는 데 사용할 토큰을 가져올 수 있도록 지원하는 기본 형식 세트를 제공합니다.

앱에 인증을 추가하는 경우에는 Microsoft.AspNetCore.Components.WebAssembly.Authentication 패키지를 앱에 수동으로 추가합니다.

참고 항목

.NET 앱에 패키지를 추가하는 방법에 대한 지침은 패키지 사용 워크플로에서 패키지 설치 및 관리의 문서(NuGet 설명서)를 참조하세요. NuGet.org에서 올바른 패키지 버전을 확인합니다.

인증 서비스 지원

OIDC(OpenID Connect)를 사용하여 사용자를 인증하는 지원은 패키지에서 제공하는 확장 메서드를 사용하여 AddOidcAuthentication 서비스 컨테이너에 Microsoft.AspNetCore.Components.WebAssembly.Authentication 등록됩니다.

AddOidcAuthentication 메서드는 콜백을 받아서 OIDC를 사용하여 앱을 인증하는 데 필요한 매개 변수를 구성합니다. 앱을 구성하는 데 필요한 값은 OIDC 규격 IP에서 얻을 수 있습니다. 앱을 등록할 때 값을 확인하세요. 앱 등록은 보통 온라인 포털에서 진행됩니다.

새 앱인 경우 다음 구성에서 {AUTHORITY}{CLIENT ID} 자리 표시자에 대한 값을 제공합니다. 앱의 IP에서 사용하는 데 필요한 기타 구성 값을 제공합니다. 예제는 Google에 대한 것이며 PostLogoutRedirectUri, RedirectUriResponseType이 필요합니다. 앱에 인증을 추가하려면 자리 표시자에 대한 값과 기타 구성 값을 사용하여 다음 코드 및 구성을 앱에 수동으로 추가합니다.

Program 파일에서:

builder.Services.AddOidcAuthentication(options =>
{
    builder.Configuration.Bind("Local", options.ProviderOptions);
});

wwwroot/appsettings.json 구성

구성은 wwwroot/appsettings.json 파일에서 제공합니다.

{
  "Local": {
    "Authority": "{AUTHORITY}",
    "ClientId": "{CLIENT ID}"
  }
}

액세스 토큰 범위

Blazor WebAssembly 템플릿은 openidprofile의 기본 범위를 자동으로 구성합니다.

Blazor WebAssembly 템플릿은 앱이 보안 API에 대한 액세스 토큰을 요청하도록 자동으로 구성하지 않습니다. 로그인 흐름의 일부로 액세스 토큰을 프로비저닝하려면 OidcProviderOptions의 기본 토큰 범위에 범위를 추가합니다. 앱에 인증을 추가하려면 다음 코드를 수동으로 추가하고 범위 URI를 구성합니다.

Program 파일에서:

builder.Services.AddOidcAuthentication(options =>
{
    ...
    options.ProviderOptions.DefaultScopes.Add("{SCOPE URI}");
});

자세한 내용은 ‘추가 시나리오’ 문서의 다음 섹션을 참조하세요.

Imports 파일

Microsoft.AspNetCore.Components.Authorization 네임스페이스는 _Imports.razor 파일을 통해 앱 전체에서 사용할 수 있게 됩니다.

@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using {APPLICATION ASSEMBLY}
@using {APPLICATION ASSEMBLY}.Shared

인덱스 페이지

인덱스 페이지(wwwroot/index.html)는 JavaScript로 AuthenticationService를 정의하는 스크립트를 포함합니다. AuthenticationService는 OIDC 프로토콜의 하위 수준 세부 정보를 처리합니다. 앱은 내부적으로 스크립트에 정의된 메서드를 호출하여 인증 작업을 수행합니다.

<script src="_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"></script>

App 구성 요소

App 구성 요소(App.razor)는 Blazor Server 앱에 있는 App 구성 요소와 비슷합니다.

  • AuthorizeRouteView 구성 요소는 현재 사용자가 지정된 페이지에 액세스할 수 있는 권한이 부여받았는지 확인하고 그러지 않은 경우 RedirectToLogin 구성 요소를 렌더링합니다.
  • RedirectToLogin 구성 요소는 권한 없는 사용자를 로그인 페이지로 리디렉션하는 기능을 관리합니다.
  • CascadingAuthenticationState 구성 요소는 앱에 AuthenticationState 대한 노출을 rest 관리합니다.
  • AuthorizeRouteView 구성 요소는 현재 사용자가 지정된 페이지에 액세스할 수 있는 권한이 부여받았는지 확인하고 그러지 않은 경우 RedirectToLogin 구성 요소를 렌더링합니다.
  • RedirectToLogin 구성 요소는 권한 없는 사용자를 로그인 페이지로 리디렉션하는 기능을 관리합니다.

ASP.NET Core 릴리스 간 프레임워크 변경으로 인해 App 구성 요소의 Razor 변경 내용(App.razor)은 이 섹션에 표시되지 않습니다. 지정된 릴리스의 구성 요소의 변경 내용을 검사하려면 다음 방법 중 하나를 사용합니다.

  • 사용하려는 ASP.NET Core 버전의 기본 Blazor WebAssembly 프로젝트 템플릿에서 인증을 위해 프로비전된 앱을 만듭니다. 생성된 앱에서 App 구성 요소(App.razor)를 검사합니다.

  • 참조 소스에서 App 구성 요소(App.razor)를 검사합니다. 분기 선택기에서 버전을 선택하고 수년에 걸쳐 이동했기 때문에 리포지토리 폴더에서 구성 요소를 ProjectTemplates 검색합니다.

    참고 항목

    .NET 참조 원본의 설명서 링크는 일반적으로 다음 릴리스의 .NET을 위한 현재 개발을 나타내는 리포지토리의 기본 분기를 로드합니다. 특정 릴리스를 위한 태그를 선택하려면 Switch branches or tags(분기 또는 태그 전환) 드롭다운 목록을 사용합니다. 자세한 내용은 ASP.NET Core 소스 코드(dotnet/AspNetCore.Docs #26205)의 버전 태그를 선택하는 방법을 참조하세요.

RedirectToLogin 구성 요소

RedirectToLogin 구성 요소(RedirectToLogin.razor)는 다음을 수행합니다.

  • 로그인 페이지로의 권한 없는 사용자 리디렉션을 관리합니다.
  • 사용자가 액세스하려는 현재 URL은 다음을 사용하여 인증에 성공한 경우 해당 페이지로 반환될 수 있도록 유지 관리됩니다.

참조 소스에서 RedirectToLogin 구성 요소를 검사합니다. 구성 요소의 위치는 시간이 지남에 따라 변경되므로 GitHub 검색 도구를 사용하여 구성 요소를 찾습니다.

참고 항목

.NET 참조 원본의 설명서 링크는 일반적으로 다음 릴리스의 .NET을 위한 현재 개발을 나타내는 리포지토리의 기본 분기를 로드합니다. 특정 릴리스를 위한 태그를 선택하려면 Switch branches or tags(분기 또는 태그 전환) 드롭다운 목록을 사용합니다. 자세한 내용은 ASP.NET Core 소스 코드(dotnet/AspNetCore.Docs #26205)의 버전 태그를 선택하는 방법을 참조하세요.

LoginDisplay 구성 요소

LoginDisplay 구성 요소(LoginDisplay.razor)는 MainLayout 구성 요소(MainLayout.razor)에서 렌더링되고 다음 동작을 관리합니다.

  • 인증된 사용자의 경우:
    • 현재 사용자 이름을 표시합니다.
    • ASP.NET Core Identity에 있는 사용자 프로필 페이지로 연결되는 링크를 제공합니다.
    • 앱에서 로그아웃하는 단추를 제공합니다.
  • 익명 사용자의 경우:
    • 등록 옵션을 제공합니다.
    • 로그인 옵션을 제공합니다.

ASP.NET Core 릴리스 간 프레임워크 변경으로 인해 LoginDisplay 구성 요소의 Razor 변경 내용은 이 섹션에 표시되지 않습니다. 지정된 릴리스의 구성 요소의 변경 내용을 검사하려면 다음 방법 중 하나를 사용합니다.

  • 사용하려는 ASP.NET Core 버전의 기본 Blazor WebAssembly 프로젝트 템플릿에서 인증을 위해 프로비전된 앱을 만듭니다. 생성된 앱에서 LoginDisplay 구성 요소를 검사합니다.

  • 참조 소스에서 LoginDisplay 구성 요소를 검사합니다. 구성 요소의 위치는 시간이 지남에 따라 변경되므로 GitHub 검색 도구를 사용하여 구성 요소를 찾습니다. true와 같은 Hosted에 대한 템플릿 콘텐츠가 사용됩니다.

    참고 항목

    .NET 참조 원본의 설명서 링크는 일반적으로 다음 릴리스의 .NET을 위한 현재 개발을 나타내는 리포지토리의 기본 분기를 로드합니다. 특정 릴리스를 위한 태그를 선택하려면 Switch branches or tags(분기 또는 태그 전환) 드롭다운 목록을 사용합니다. 자세한 내용은 ASP.NET Core 소스 코드(dotnet/AspNetCore.Docs #26205)의 버전 태그를 선택하는 방법을 참조하세요.

Authentication 구성 요소

Authentication 구성 요소에 의해 생성된 페이지(Pages/Authentication.razor)는 다른 인증 단계를 처리하는 데 필요한 경로를 정의합니다.

RemoteAuthenticatorView 구성 요소는 다음과 같습니다.

@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication

<RemoteAuthenticatorView Action="@Action" />

@code {
    [Parameter]
    public string? Action { get; set; }
}

참고 항목

NRT(Nullable 참조 형식) 및 .NET 컴파일러 null 상태 정적 분석은 .NET 6 이상의 ASP.NET Core에서 지원됩니다. .NET 6에서 ASP.NET Core가 릴리스되기 전에 형식은 string null 형식 지정(?)없이 표시됩니다.

문제 해결

로깅

인증에 Blazor WebAssembly 디버그 또는 추적 로깅을 사용하도록 설정하려면 문서 버전 선택기가 ASP.NET Core Blazor 7.0 이상으로 설정된 ASP.NET Core 로깅의 클라이언트 쪽 인증 로깅 섹션을 참조하세요.

일반 오류

  • 앱 또는 IP(Identity 공급자)의 잘못된 구성

    가장 일반적인 오류는 잘못된 구성으로 인해 발생합니다. 다음은 몇 가지 예입니다.

    • 시나리오의 요구 사항에 따라, 누락되거나 잘못된 권한, 인스턴스, 테넌트 ID, 테넌트 도메인, 클라이언트 ID 또는 리디렉션 URI 때문에 앱에서 클라이언트를 인증하지 못합니다.
    • 잘못된 요청 범위는 클라이언트가 서버 웹 API 엔드포인트에 액세스하지 못하게 합니다.
    • 서버 API 권한이 잘못되거나 누락되어 클라이언트가 서버 웹 API 엔드포인트에 액세스할 수 없습니다.
    • IP 앱 등록의 리디렉션 URI에 구성된 것과 다른 포트에서 앱을 실행합니다. Microsoft Entra ID 및 개발 테스트 주소에서 localhost 실행되는 앱에는 포트가 필요하지 않지만 앱의 포트 구성 및 앱이 실행되는 포트는 주소localhost 가 아닌 경우 일치해야 합니다.

    이 문서 지침의 구성 섹션에서는 올바른 구성의 예를 보여 줍니다. 앱 및 IP 구성을 찾는 문서의 각 섹션을 주의 깊게 확인하세요.

    구성이 올바르게 표시되면 다음을 수행합니다.

    • 애플리케이션 로그를 분석합니다.

    • 브라우저의 개발자 도구를 사용하여 클라이언트 앱과 IP 또는 서버 앱 간의 네트워크 트래픽을 검사합니다. 종종 정확한 오류 메시지 또는 문제의 원인에 대한 단서가 있는 메시지가 요청을 수행한 후 IP 또는 서버 앱에 의해 클라이언트로 반환됩니다. 개발자 도구 지침은 다음 문서에서 확인할 수 있습니다.

    • JWT(JSON 웹 토큰)가 사용되는 릴리스의 Blazor 경우 문제가 발생하는 위치에 따라 클라이언트를 인증하거나 서버 웹 API에 액세스하는 데 사용되는 토큰의 콘텐츠를 디코딩합니다. 자세한 내용은 JWT(JSON Web Token)의 콘텐츠 검사를 참조하세요.

    문서 작업 팀은 설명서 피드백 및 문서의 버그에 응답하지만(이 페이지의 피드백 섹션에서 문제 열기) 제품 지원을 제공할 수 없습니다. 앱 문제 해결을 지원하기 위해 몇 가지 퍼블릭 지원 포럼을 사용할 수 있습니다. 다음을 권장합니다.

    이전 포럼은 Microsoft에서 소유하거나 제어하지 않습니다.

    중요하지 않고 보안이나 기밀이 아니며 재현 가능한 프레임워크 버그 보고서의 경우 ASP.NET Core 제품 단위에서 문제를 여세요. 문제의 원인을 철저하게 조사했으며 자신의 노력과 퍼블릭 지원 포럼에서 커뮤니티의 도움을 받아도 해결할 수 없는 경우에만 제품 단위에서 문제를 열고 그전에는 열지 마세요. 제품 단위는 단순한 구성 오류 또는 타사 서비스와 관련된 사용 사례로 인해 손상된 개별 앱의 문제를 해결할 수 없습니다. 보고서가 본질적으로 민감하거나 기밀이거나 사이버 공격이 악용될 수 있는 제품의 잠재적 보안 결함을 설명하는 경우 보안 문제 및 버그 보고(dotnet/aspnetcoreGitHub 리포지토리)를 참조하세요.

  • ME-ID에 대한 권한 없는 클라이언트

    info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] 권한 부여에 실패했습니다. 이러한 요구 사항이 충족되지 않았습니다. DenyAnonymousAuthorizationRequirement: 인증된 사용자가 필요합니다.

    ME-ID의 로그인 콜백 오류:

    • 오류: unauthorized_client
    • 설명: AADB2C90058: The provided application is not configured to allow public clients.

    오류를 해결하려면:

    1. Azure Portal에서 앱의 매니페스트에 액세스합니다.
    2. allowPublicClient 특성null 또는 true로 설정합니다.

쿠키 및 사이트 데이터

쿠키 및 사이트 데이터가 앱을 업데이트할 때에도 유지되어 테스트 및 문제 해결에 방해가 될 수 있습니다. 앱 코드를 변경하거나 공급자를 사용하여 사용자 계정을 변경하거나 공급자 앱 구성을 변경하는 경우 다음을 지우세요.

  • 사용자 로그인 쿠키
  • 앱 쿠키
  • 캐시되고 저장된 사이트 데이터

남겨진 쿠키 및 사이트 데이터로 인해 테스트 및 문제 해결이 지장을 받지 않도록 하려면 다음을 수행합니다.

  • 브라우저 구성
    • 브라우저에서 브라우저를 닫을 때마다 모든 cookie 및 사이트 데이터를 삭제하도록 구성할 수 있는지 테스트합니다.
    • 앱, 테스트 사용자 또는 공급자 구성을 변경할 때 수동으로 또는 IDE를 통해 브라우저를 닫습니다.
  • 사용자 지정 명령을 사용하여 Visual Studio에서 InPrivate 또는 Incognito 모드로 브라우저를 엽니다.
    • Visual Studio의 실행 단추를 통해 브라우저 선택 대화 상자를 엽니다.
    • 추가 단추를 선택합니다.
    • 프로그램 필드에서 브라우저의 경로를 제공합니다. 다음 실행 파일 경로는 Windows 10에서 일반적인 설치 위치입니다. 브라우저가 다른 위치에 설치되어 있거나 Windows 10을 사용하지 않는 경우 브라우저 실행 파일의 경로를 제공합니다.
      • Microsoft Edge: C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
      • Google Chrome: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
      • Mozilla Firefox: C:\Program Files\Mozilla Firefox\firefox.exe
    • 인수 필드에서 브라우저가 InPrivate 또는 Incognito 모드에서 여는 데 사용하는 명령줄 옵션을 제공합니다. 일부 브라우저에는 앱의 URL이 필요합니다.
      • Microsoft Edge: 사용 -inprivate.
      • Google Chrome: 자리 표시자가 열 URL인 경우{URL}(예https://localhost:5001: )를 사용합니다--incognito --new-window {URL}.
      • Mozilla Firefox: 자리 표시자가 열 URL인 경우(예https://localhost:5001: )를 사용합니다.-private -url {URL}{URL}
    • 이름 필드에 이름을 입력합니다. 예들 들어 Firefox Auth Testing입니다.
    • 확인 단추를 선택합니다.
    • 앱 테스트를 반복할 때마다 브라우저 프로필을 선택할 필요가 없도록 하려면 기본값으로 설정 단추를 사용하여 프로필을 기본값으로 설정합니다.
    • 앱, 테스트 사용자 또는 공급자 구성을 변경할 때 IDE를 통해 브라우저를 닫습니다.

앱 업그레이드

개발 컴퓨터의 .NET Core SDK 또는 앱 내의 패키지 버전을 업그레이드하거나 앱 내 패키지 버전을 변경한 후 즉시 작동 중인 앱에서 오류가 발생할 수 있습니다. 경우에 따라 중요한 업그레이드를 수행할 때 일관되지 않은 패키지로 인해 응용 프로그램이 중단될 수 있습니다. 이러한 대부분의 문제는 다음 지침에 따라 수정할 수 있습니다.

  1. 명령 셸에서 dotnet nuget locals all --clear를 실행하여 로컬 시스템의 NuGet 패키지 캐시를 지웁니다.
  2. 프로젝트의 binobj 폴더를 삭제합니다.
  3. 프로젝트를 복원하고 다시 빌드합니다.
  4. 앱을 다시 배포하기 전에 서버의 배포 폴더에 있는 모든 파일을 삭제합니다.

참고 항목

앱의 대상 프레임워크와 호환되지 않는 패키지 버전의 사용은 지원되지 않습니다. 패키지에 대한 자세한 내용은 NuGet 갤러리 또는 FuGet 패키지 탐색기를 사용하세요.

Server 실행

호스트된 Blazor WebAssembly솔루션을 테스트하고 문제를 해결할 때 Server 프로젝트에서 앱을 실행하고 있는지 확인합니다.

사용자 검사

다음 User 구성 요소는 앱에서 직접 사용하거나 추가 사용자 지정의 기준으로 사용할 수 있습니다.

User.razor:

@page "/user"
@attribute [Authorize]
@using System.Text.Json
@using System.Security.Claims
@inject IAccessTokenProvider AuthorizationService

<h1>@AuthenticatedUser?.Identity?.Name</h1>

<h2>Claims</h2>

@foreach (var claim in AuthenticatedUser?.Claims ?? Array.Empty<Claim>())
{
    <p class="claim">@(claim.Type): @claim.Value</p>
}

<h2>Access token</h2>

<p id="access-token">@AccessToken?.Value</p>

<h2>Access token claims</h2>

@foreach (var claim in GetAccessTokenClaims())
{
    <p>@(claim.Key): @claim.Value.ToString()</p>
}

@if (AccessToken != null)
{
    <h2>Access token expires</h2>

    <p>Current time: <span id="current-time">@DateTimeOffset.Now</span></p>
    <p id="access-token-expires">@AccessToken.Expires</p>

    <h2>Access token granted scopes (as reported by the API)</h2>

    @foreach (var scope in AccessToken.GrantedScopes)
    {
        <p>Scope: @scope</p>
    }
}

@code {
    [CascadingParameter]
    private Task<AuthenticationState> AuthenticationState { get; set; }

    public ClaimsPrincipal AuthenticatedUser { get; set; }
    public AccessToken AccessToken { get; set; }

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
        var state = await AuthenticationState;
        var accessTokenResult = await AuthorizationService.RequestAccessToken();

        if (!accessTokenResult.TryGetToken(out var token))
        {
            throw new InvalidOperationException(
                "Failed to provision the access token.");
        }

        AccessToken = token;

        AuthenticatedUser = state.User;
    }

    protected IDictionary<string, object> GetAccessTokenClaims()
    {
        if (AccessToken == null)
        {
            return new Dictionary<string, object>();
        }

        // header.payload.signature
        var payload = AccessToken.Value.Split(".")[1];
        var base64Payload = payload.Replace('-', '+').Replace('_', '/')
            .PadRight(payload.Length + (4 - payload.Length % 4) % 4, '=');

        return JsonSerializer.Deserialize<IDictionary<string, object>>(
            Convert.FromBase64String(base64Payload));
    }
}

JWT(JSON Web Token)의 콘텐츠 검사

JWT(JSON Web Token)를 디코딩하려면 Microsoft의 jwt.ms 도구를 사용합니다. UI의 값은 브라우저에 남겨지지 않습니다.

인코딩된 JWT 예제(표시를 위해 축약됨):

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Ilg1ZVhrNHh5b2pORnVtMWtsMll0djhkbE5QNC1j ... bQdHBHGcQQRbW7Wmo6SWYG4V_bU55Ug_PW4pLPr20tTS8Ct7_uwy9DWrzCMzpD-EiwT5IjXwlGX3IXVjHIlX50IVIydBoPQtadvT7saKo1G5Jmutgq41o-dmz6-yBMKV2_nXA25Q

Azure AAD B2C에 대해 인증하는 앱용 도구에 의해 디코딩된 JWT 예제:

{
  "typ": "JWT",
  "alg": "RS256",
  "kid": "X5eXk4xyojNFum1kl2Ytv8dlNP4-c57dO6QGTVBwaNk"
}.{
  "exp": 1610059429,
  "nbf": 1610055829,
  "ver": "1.0",
  "iss": "https://mysiteb2c.b2clogin.com/11112222-bbbb-3333-cccc-4444dddd5555/v2.0/",
  "sub": "aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb",
  "aud": "00001111-aaaa-2222-bbbb-3333cccc4444",
  "nonce": "bbbb0000-cccc-1111-dddd-2222eeee3333",
  "iat": 1610055829,
  "auth_time": 1610055822,
  "idp": "idp.com",
  "tfp": "B2C_1_signupsignin"
}.[Signature]

추가 리소스