다음을 통해 공유


ASP.NET Core Blazor 인증 및 권한 부여

Note

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

Warning

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

Important

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

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

이 문서에서는 Blazor 앱의 보안 구성 및 관리를 위한 ASP.NET Core 지원에 대해 설명합니다.

Blazor 기존 ASP.NET Core 인증 메커니즘을 사용하여 사용자의 ID를 설정합니다. 정확한 메커니즘은 앱이 Blazor 호스트되는 방법, 서버 쪽 또는 클라이언트 쪽에 따라 달라집니다.

보안 시나리오는 앱에서 Blazor 서버 쪽과 클라이언트 쪽을 실행하는 권한 부여 코드 간에 다릅니다. 서버에서 실행되는 권한 부여 코드의 경우 권한 부여 검사는 앱 및 구성 요소 영역에 대한 액세스 규칙을 적용할 수 있습니다. 클라이언트 쪽 코드 실행을 변조할 수 있으므로 클라이언트에서 실행되는 권한 부여 코드를 신뢰할 수 없으므로 액세스 규칙을 절대적으로 적용하거나 클라이언트 쪽 콘텐츠의 표시를 제어할 수 없습니다.

권한 부여 규칙 적용을 보장해야 하는 경우 클라이언트 쪽 코드에서 권한 부여 검사를 구현하지 마세요. Blazor Web App 권한 부여 검사 및 규칙 적용을 위해 SSR(서버 쪽 렌더링)만 사용하는 빌드.

권한 부여 규칙 적용 및 데이터 및 코드의 보안을 보장해야 하는 경우 클라이언트 쪽 앱을 개발하지 마세요. 앱을 빌드합니다 Blazor Server .

Razor 페이지 권한 부여 규칙은 라우팅 가능한 Razor 구성 요소에 적용되지 않습니다. 라우팅할 수 없는 구성 요소가 Pages 앱페이지에 포함된 경우 페이지의 권한 부여 규칙은 페이지의 나머지 콘텐츠와 함께 구성 요소에 간접적으로 영향을 줍니다.

ASP.NET Core Identity는 대부분의 경우 Blazor 앱 클라이언트-서버 커뮤니케이션 모델이 아닌 HTTP 요청 및 응답 커뮤니케이션의 컨텍스트에서 작동하도록 설계되었습니다. 사용자 관리에 ASP.NET Core Identity를 사용하는 ASP.NET Core 앱은 사용자 등록, 로그인, 로그아웃 및 기타 사용자 관리 작업과 같은 Razor 관련 UI에 Razor 구성 요소 대신 Identity Pages를 사용해야 합니다. 작업을 직접 처리하는 Razor 구성 요소를 빌드 Identity 하는 것은 여러 시나리오에서 가능하지만 Microsoft에서 권장하거나 지원하지 않습니다.

ASP.NET Core 추상화(예: SignInManager<TUser>UserManager<TUser>)는 Razor 구성 요소에서 지원되지 않습니다. ASP.NET Core Identity를 Blazor와 함께 사용하는 방법에 대한 자세한 내용은 ASP.NET Core Identity를 서버 쪽 Blazor 앱에 스캐폴드하는 방법을 참조하세요.

Note

이 문서의 코드 예제에서는 NRT(nullable 참조 형식) 및 .NET 컴파일러 null 상태 정적 분석을 채택합니다. 이 분석은 .NET 6 이상의 ASP.NET Core에서 지원됩니다. .NET 5 이하를 대상으로 하는 경우 이 문서의 예제에서 null 형식 지정(?)을 제거합니다.

중요한 데이터 및 자격 증명을 안전하게 유지 관리

앱 비밀, 연결 문자열, 자격 증명, 암호, PIN(개인 식별 번호), 프라이빗 .NET/C# 코드 또는 프라이빗 키/토큰을 항상 안전하지 않은 클라이언트 쪽 코드에 저장하지 마세요. 클라이언트 쪽 Blazor 코드는 제어하는 보안 웹 API를 통해 보안 서비스 및 데이터베이스에 액세스해야 합니다.

테스트/스테이징 및 프로덕션 환경에서 서버 쪽 Blazor 코드 및 웹 API는 프로젝트 코드 또는 구성 파일 내에서 자격 증명을 유지 관리하지 않는 보안 인증 흐름을 사용해야 합니다. 로컬 개발 테스트 외에는 환경 변수가 가장 안전한 방법이 아니므로 환경 변수를 사용하여 중요한 데이터를 저장하는 것을 피하는 것이 좋습니다. 로컬 개발 테스트의 경우 중요한 데이터를 보호하기 위해 Secret Manager 도구를 사용하는 것이 좋습니다. 자세한 내용은 다음 리소스를 참조하세요.

클라이언트 쪽 및 서버 쪽 로컬 개발 및 테스트의 경우 Secret Manager 도구를 사용하여 중요한 자격 증명을 보호합니다.

Microsoft Azure 서비스에 대한 관리 ID

Microsoft Azure 서비스의 경우 관리 ID를 사용하는 것이 좋습니다. 관리 ID는 앱 코드에 자격 증명을 저장하지 않고 Azure 서비스에 안전하게 인증합니다. 자세한 내용은 다음 리소스를 참조하세요.

위조 방지 지원

Blazor 템플릿:

AntiforgeryToken 구성 요소는 위조 방지 토큰을 숨겨진 필드로 렌더링하고 이 구성 요소는 양식(EditForm) 인스턴스에 자동으로 추가됩니다. 자세한 내용은 ASP.NET Core Blazor 양식 개요를 참조하세요.

AntiforgeryStateProvider 서비스는 현재 세션과 연결된 위조 방지 토큰에 대한 액세스를 제공합니다. 서비스를 삽입하고 해당 메서드를 GetAntiforgeryToken() 호출하여 현재 AntiforgeryRequestToken를 가져옵니다. 자세한 내용은 ASP.NET Core Blazor 앱에서 웹 API 호출을 참조하세요.

Blazor 는 요청 토큰을 구성 요소 상태로 저장하므로 요청에 액세스할 수 없는 경우에도 대화형 구성 요소에서 위조 방지 토큰을 사용할 수 있습니다.

Note

위조 방지 대책은 양식 데이터를 서버로 제출할 때 인코딩 방식이 application/x-www-form-urlencoded, multipart/form-data, 또는 text/plain로 설정된 경우에만 필요합니다. 이는 이들이 유효한 양식 인코딩 방식이기 때문입니다.

자세한 내용은 다음 리소스를 참조하세요.

서버 쪽 Blazor 인증

서버 쪽 Blazor 앱은 ASP.NET Core 앱과 동일한 방식으로 보안을 위해 구성됩니다. 자세한 내용은 ASP.NET Core 보안 항목의 문서를 참조하세요.

인증 컨텍스트는 앱이 시작될 때만 설정되며, 이는 앱이 클라이언트와의 연결을 통해 SignalR WebSocket 에 처음 연결하는 경우입니다. 인증은 cookie 또는 다른 전달자 토큰을 기반으로 할 수 있지만, 인증은 SignalR 허브를 통해 전적으로 회로 내에서 관리됩니다. 인증 컨텍스트는 회로의 수명 동안 유지 관리됩니다. 앱은 30분마다 정기적으로 사용자의 인증 상태를 다시 검증합니다.

앱이 사용자 지정 서비스에 대한 사용자를 캡처하거나 사용자 업데이트에 반응해야 하는 경우 ASP.NET Core 서버 쪽 및 Blazor Web App 추가 보안 시나리오를 참조하세요.

Blazor 는 모든 페이지 탐색에서 쿠키를 사용하여 새 HTTP 요청을 만드는 기존의 서버 렌더링 웹앱과 다릅니다. 탐색 이벤트 중에 인증이 확인됩니다. 그러나 쿠키는 관련되지 않습니다. 쿠키는 서버에 HTTP 요청을 할 때만 전송되며, 이는 사용자가 앱에서 Blazor 탐색할 때 수행되지 않습니다. 탐색하는 동안, 회로 내에서 사용자의 인증 상태가 확인되며, 추상화를 사용하여 서버에서 언제든지 업데이트할 수 있습니다.

Important

탐색 중에 인증 유효성 검사를 달성하기 위해 사용자 지정 NavigationManager 을 구현하는 것은 권장되지 않습니다. 앱이 탐색 중에 사용자 지정 인증 상태 논리를 실행해야 하는 경우 사용자 지정 AuthenticationStateProvider을 사용합니다.

Note

이 문서의 코드 예제에서는 NRT(nullable 참조 형식) 및 .NET 컴파일러 null 상태 정적 분석을 채택합니다. 이 분석은 .NET 6 이상의 ASP.NET Core에서 지원됩니다. .NET 5 이하를 대상으로 하는 경우 이 문서의 예제에서 null 형식 지정(?)을 제거합니다.

기본 제공 또는 사용자 지정 AuthenticationStateProvider 서비스는 ASP.NET Core HttpContext.User에서 인증 상태 데이터를 가져옵니다. 이것이 바로 인증 상태가 기존의 ASP.NET Core 인증 메커니즘과 통합되는 방식입니다.

공유 상태

서버 쪽 Blazor 앱은 서버 메모리에 있으며 여러 앱 세션은 동일한 프로세스 내에서 호스트됩니다. 각 앱 세션에서 Blazor은 자체 종속성 주입 컨테이너 범위로 회로를 시작합니다. 따라서 범위가 지정된 서비스는 각 Blazor 세션마다 고유합니다.

Warning

매우 주의하지 않는 한 싱글톤 서비스를 사용하는 동일한 서버 공유 상태에서는 앱을 사용하지 않는 것이 좋습니다. 회로 간 사용자 상태 누수와 같은 보안 취약성이 도입될 수 있기 때문입니다.

Blazor 앱에서 상태 저장 싱글톤 서비스를 사용할 수 있습니다, 전제 조건은 해당 서비스가 특별히 설계된 것입니다. 예를 들어 메모리 캐시에는 지정된 항목에 액세스하는 데 키가 필요하기 때문에 싱글톤 메모리 캐시를 사용할 수 있습니다. 사용자가 캐시와 함께 사용되는 캐시 키를 제어할 수 없다고 가정하면 캐시에 저장된 상태는 회로 간에 누출되지 않습니다.

상태 관리에 대한 일반적인 지침은 ASP.NET Core Blazor 상태 관리 개요를 참조하세요.

중요한 데이터 및 자격 증명의 서버 쪽 보안

테스트/스테이징 및 프로덕션 환경에서 서버 쪽 Blazor 코드 및 웹 API는 프로젝트 코드 또는 구성 파일 내에서 자격 증명을 유지 관리하지 않는 보안 인증 흐름을 사용해야 합니다. 로컬 개발 테스트 외에는 환경 변수가 가장 안전한 방법이 아니므로 환경 변수를 사용하여 중요한 데이터를 저장하는 것을 피하는 것이 좋습니다. 로컬 개발 테스트의 경우 중요한 데이터를 보호하기 위해 Secret Manager 도구를 사용하는 것이 좋습니다. 자세한 내용은 다음 리소스를 참조하세요.

클라이언트 쪽 및 서버 쪽 로컬 개발 및 테스트의 경우 Secret Manager 도구를 사용하여 중요한 자격 증명을 보호합니다.

프로젝트 템플릿

ASP.NET Core 도구 지침을 따라 새 서버-측 앱을 만듭니다.

서버 쪽 앱 템플릿을 선택하고 프로젝트를 구성한 후 인증 유형에서 앱의 인증을 선택합니다.

  • 없음 (기본값): 인증이 없습니다.
  • 개별 계정: 사용자 계정은 ASP.NET Core Identity를 사용하여 앱 내에 저장됩니다.
  • 없음 (기본값): 인증이 없습니다.
  • 개별 계정: 사용자 계정은 ASP.NET Core Identity를 사용하여 앱 내에 저장됩니다.
  • Microsoft ID 플랫폼: 자세한 내용은 추가 리소스 섹션의 링크를 참조하세요.
  • Windows: Windows 인증을 사용합니다.

Blazor Identity UI(개별 계정)

Blazor는 Blazor 대한 인증 옵션을 선택할 때 전체 Identity기반 UI 생성을 지원합니다.

템플릿은 SQL Server 데이터베이스를 위한 Blazor Web App 코드를 Identity 으로 스캐폴드합니다. 명령줄 버전은 SQLite를 사용하며 SQLite 데이터베이스를 Identity포함합니다.

템플릿:

  • 인증된 사용자를 사용하여 대화형 서버 쪽 렌더링(대화형 SSR) 및 CSR(클라이언트 쪽 렌더링) 시나리오를 지원합니다.
  • 사용자 로그인 및 로그아웃과 같은 일상적인 인증 작업에 대한 구성 요소 및 관련 논리를 추가 IdentityRazor 합니다. Identity 또한 구성 요소는 타사 앱을 사용하는 Identity다단계 인증과 같은 고급 기능도 지원합니다. Identity 구성 요소 자체는 대화형 작업을 지원하지 않습니다.
  • Identity관련 패키지 및 종속성을 추가합니다.
  • Identity에서 _Imports.razor 패키지를 참조합니다.
  • 사용자 지정 사용자 Identity 클래스(ApplicationUser)를 만듭니다.
  • EF Core 데이터베이스 컨텍스트를 만들고 ApplicationDbContext을 등록합니다.
  • 기본 제공 Identity 엔드포인트에 대한 라우팅을 구성합니다.
  • 유효성 검사 및 비즈니스 논리를 포함합니다 Identity .

서버 프로젝트의 Blazor 폴더에 있는 Identity 및 Pages 폴더에서 Shared 프레임워크의 Components/Account 구성 요소를 검사하려면 Blazor Web App 프로젝트 템플릿dotnet/aspnetcore (GitHub 리포지토리)에 액세스합니다.

Interactive WebAssembly 또는 대화형 자동 렌더링 모드를 선택하면 서버는 모든 인증 및 권한 부여 요청을 처리하고 Identity 구성 요소는 '주 프로젝트의 서버에서 Blazor Web App정적으로 렌더링됩니다.

프레임워크는 서버 및 클라이언트(AuthenticationStateProvider) 프로젝트 모두에서 사용자 지정 .Client 을 제공하여 사용자의 인증 상태를 브라우저로 전달합니다. 서버 프로젝트는 AddAuthenticationStateSerialization를 호출하고 클라이언트 프로젝트는 AddAuthenticationStateDeserialization를 호출합니다. 클라이언트가 아닌 서버에서 인증하면 미리 렌더링하는 동안 및 .NET WebAssembly 런타임이 초기화되기 전에 앱이 인증 상태에 액세스할 수 있습니다. 사용자 지정 AuthenticationStateProvider 구현은 영구 구성 요소 상태 서비스 (PersistentComponentState)를 사용하여 인증 상태를 HTML 주석으로 직렬화한 다음 WebAssembly에서 다시 읽어 새 AuthenticationState 인스턴스를 만듭니다. 자세한 내용은 S 섹션의 인증 상태 Blazor Web App관리를 참조하세요.

대화형 서버 솔루션 IdentityRevalidatingAuthenticationStateProvider의 경우에만, Components/Account/IdentityRevalidatingAuthenticationStateProvider.cs (Blazor Web App) 프로젝트 템플릿의 서버 프로젝트(dotnet/aspnetcore GitHub 리포지토리)는 대화형 회로가 연결된 동안 30분마다 연결된 사용자의 보안 스탬프를 다시 검증하는 서버 측 입니다.

Interactive WebAssembly 또는 대화형 자동 렌더링 모드를 선택하면 서버는 모든 인증 및 권한 부여 요청을 처리하고 Identity 구성 요소는 '주 프로젝트의 서버에서 Blazor Web App정적으로 렌더링됩니다. 프로젝트 템플릿에는 서버와 브라우저 간에 사용자의 인증 상태를 동기화하는 클래스(참조 원본)가 프로젝트에 포함됩니다PersistentAuthenticationStateProvider..Client 클래스는 .의 사용자 지정 구현입니다 AuthenticationStateProvider. 공급자는 영구 구성 요소 상태 서비스인증 상태를 미리 렌더링하고 페이지에 유지합니다.

주 프로젝트에서 인증 상태 공급자는 의 경우 서버 프로젝트의 폴더에 있는 로 명명되며, 이는 프로젝트 템플릿( GitHub 리포지토리)을 통해 가능합니다 (서버 대화형 솔루션에만 해당). 또는 이름이 동일한 폴더에 지정되며, 이는 WebAssembly 또는 자동 대화형 솔루션에 해당됩니다.

Blazor Identity는 팩터리에서 생성되지 않은 DbContext 인스턴스에 의존합니다. 이 의도는 프로젝트 템플릿의 구성 요소가 상호작용을 지원하지 않고도 정적으로 렌더링하기에 충분하기 때문입니다.

비-Identity 구성 요소에 전역 대화형 렌더링 모드를 적용하는 동시에 Identity 구성 요소에 정적 SSR을 적용하는 방법에 대한 설명은 ASP.NET Core Blazor 렌더링 모드를 참조하세요.

미리 렌더링된 상태를 유지하는 방법에 대한 자세한 내용은 ASP.NET Core Blazor 미리 렌더링된 상태 지속성을 참조하세요.

Note

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

Blazor Web App 내 인증 상태 관리

이 섹션은 Blazor Web App를 채택한 경우에 적용됩니다.

  • 개별 계정
  • 클라이언트 쪽 렌더링(CSR, WebAssembly 기반 대화형 작업).

클라이언트 쪽 인증 상태 공급자는 내부에서 Blazor 만 사용되며 ASP.NET Core 인증 시스템과 통합되지 않습니다. 미리 렌더링하는 Blazor 동안 페이지에 정의된 메타데이터를 준수하고 ASP.NET Core 인증 시스템을 사용하여 사용자가 인증되었는지 확인합니다. 사용자가 한 페이지에서 다른 페이지로 이동하면 클라이언트 쪽 인증 공급자가 사용됩니다. 사용자가 페이지를 새로 고치면(전체 페이지 다시 로드) 클라이언트 쪽 인증 상태 공급자는 서버의 인증 결정에 관여하지 않습니다. 사용자의 상태가 서버에 의해 유지되지 않으므로 유지 관리되는 모든 인증 상태 클라이언트 쪽이 손실됩니다.

이 문제를 해결하기 위해 가장 좋은 방법은 ASP.NET Core 인증 시스템 내에서 인증을 수행하는 것입니다. 클라이언트 쪽 인증 상태 공급자는 사용자의 인증 상태를 반영하기만 합니다. 인증 상태 공급자를 사용하여 이 작업을 수행하는 방법에 대한 예제는 Blazor Web App 프로젝트 템플릿에 제공되며, 아래에 설명되어 있습니다.

서버 프로젝트의 Program 파일에서 서버 측 AddAuthenticationStateSerialization이 반환한 AuthenticationState을(를) AuthenticationStateProvider()를 사용하여 시리얼라이즈하는 PersistentComponentState을 호출합니다.

builder.Services.AddRazorComponents()
    .AddInteractiveWebAssemblyComponents()
    .AddAuthenticationStateSerialization();

API는 브라우저에서 액세스에 대한 서버 쪽 이름 및 역할 클레임만 직렬화합니다. 모든 클레임을 포함하려면 서버 측 호출에서 SerializeAllClaimstrue로 설정해야 합니다: AddAuthenticationStateSerialization.

builder.Services.AddRazorComponents()
    .AddInteractiveWebAssemblyComponents()
    .AddAuthenticationStateSerialization(
        options => options.SerializeAllClaims = true);

클라이언트(.Client) 프로젝트의 Program 파일에서 AddAuthenticationStateDeserialization를 호출하여, 서버 AuthenticationStateProvider를 사용해 역직렬화된 AuthenticationStateAuthenticationStateData를 추가하고 영구 구성 요소 상태 서비스(PersistentComponentState)를 사용합니다. 서버 프로젝트에 해당 호출 AddAuthenticationStateSerialization 이 있어야 합니다.

builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthenticationStateDeserialization();

Note

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

스캐폴드 Identity

서버 쪽 앱으로 스캐폴딩하는 Identity 방법에 대한 자세한 내용은 Blazor참조하세요.Identity

서버 사이드 Identity 앱으로 Blazor를 스캐폴드하십시오:

외부 공급자의 추가 클레임 및 토큰

외부 공급자의 추가 클레임을 저장하려면 ASP.NET Core에서 외부 공급자의 추가 클레임 및 토큰 유지를 참조하세요.

Linux에서 Identity Server를 사용한 Azure App Service

Identity Server를 사용하여 Azure App Service on Linux에 배포할 때 발급자를 명시적으로 지정합니다. 자세한 내용은 SPA에 대한 Web API 백 엔드 보안을 위한 사용을 Identity 참조하세요.

AuthenticationStateProvider을(를) 구성 요소 범위의 서비스에 주입

사용자 지정 범위 내에서 해결 AuthenticationStateProvider 하려고 시도하지 마세요. 그러면 올바르게 초기화되지 않은 새 인스턴스 AuthenticationStateProvider 가 생성되기 때문입니다.

구성 요소로 범위가 지정된 서비스 내의 AuthenticationStateProvider에 액세스하려면 AuthenticationStateProvider을 구성 요소에 주입하고 이를 매개 변수로 서비스에 전달합니다. 이 방법을 사용하면 각 사용자 앱 인스턴스에 대해 올바른 초기화된 인스턴스 AuthenticationStateProvider 가 사용됩니다.

ExampleService.cs:

public class ExampleService
{
    public async Task<string> ExampleMethod(AuthenticationStateProvider authStateProvider)
    {
        var authState = await authStateProvider.GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity is not null && user.Identity.IsAuthenticated)
        {
            return $"{user.Identity.Name} is authenticated.";
        }
        else
        {
            return "The user is NOT authenticated.";
        }
    }
}

서비스를 특정 범위에 등록합니다. 서버 쪽 Blazor 앱에서 범위가 지정된 서비스는 클라이언트 연결 회로의 기간과 동일한 수명을 갖습니다.

Program 파일에서:

builder.Services.AddScoped<ExampleService>();

Startup.ConfigureServicesStartup.cs에서 다음을 수행합니다.

services.AddScoped<ExampleService>();

다음은 InjectAuthStateProvider 구성 요소에 대한 설명입니다.

InjectAuthStateProvider.razor:

@page "/inject-auth-state-provider"
@inherits OwningComponentBase
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>Inject <code>AuthenticationStateProvider</code> Example</h1>

<p>@message</p>

@code {
    private string? message;
    private ExampleService? ExampleService { get; set; }

    protected override async Task OnInitializedAsync()
    {
        ExampleService = ScopedServices.GetRequiredService<ExampleService>();

        message = await ExampleService.ExampleMethod(AuthenticationStateProvider);
    }
}
@page "/inject-auth-state-provider"
@inject AuthenticationStateProvider AuthenticationStateProvider
@inherits OwningComponentBase

<h1>Inject <code>AuthenticationStateProvider</code> Example</h1>

<p>@message</p>

@code {
    private string? message;
    private ExampleService? ExampleService { get; set; }

    protected override async Task OnInitializedAsync()
    {
        ExampleService = ScopedServices.GetRequiredService<ExampleService>();

        message = await ExampleService.ExampleMethod(AuthenticationStateProvider);
    }
}

자세한 내용은 OwningComponentBase에 대한 Blazor 지침을 참조하세요.

사용자 지정으로 미리 렌더링하는 동안 권한이 없는 콘텐츠 표시 AuthenticationStateProvider

사용자 지정AuthorizeView으로 미리 렌더링하는 동안 구성 요소의AuthenticationStateProvider 콘텐츠와 같이 권한이 없는 콘텐츠가 표시되지 않도록 하려면 다음 방법 중 하나를 채택합니다.

  • 미리 렌더링 사용 안 함: 루트 구성 요소가 아닌 앱의 구성 요소 계층 구조에서 가장 높은 수준의 구성 요소로 설정된 prerender 매개 변수가 있는 렌더링 모드 false 를 나타냅니다.

    Note

    루트 구성 요소인 App를 대화형으로 만드는 것은 지원되지 않습니다. 따라서 미리 렌더링은 구성 요소에서 App 직접 사용하지 않도록 설정할 수 없습니다.

    프로젝트 템플릿을 기반으로 하는 앱의 경우, Blazor Web App 구성 요소가 Routes 구성 요소 내에서 사용될 때 일반적으로 미리 렌더링이 비활성화됩니다 (App).

    <Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />
    

    또한 HeadOutlet 구성 요소의 사전 렌더링을 비활성화하십시오.

    <HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />
    

    구성 요소 인스턴스에 적용되는 렌더링 모드를 선택적으로 제어할 수 있습니다. 예를 들어 ASP.NET Core Blazor 렌더링 모드를 참조하세요.

  • 미리 렌더링 사용 안 함: _Host.cshtml 파일을 열고 render-mode 특성을 Server으로 변경합니다.

    <component type="typeof(App)" render-mode="Server" />
    
  • 앱 시작 전에 사용자를 서버에서 인증합니다: 이 방법을 채택하려면, 앱은 사용자의 초기 요청에 Identity 기반의 로그인 페이지 또는 뷰로 응답하고, 인증될 때까지 Blazor 엔드포인트에 대한 요청을 하지 않도록 해야 합니다. 자세한 내용은 권한 부여로 보호되는 사용자 데이터를 사용하여 ASP.NET Core 앱 만들기를 참조하세요. 인증 후 미리 렌더링된 Razor 구성 요소의 권한 없는 콘텐츠는 사용자가 콘텐츠를 볼 수 있는 권한이 없는 경우에만 표시됩니다.

사용자 상태 관리

이름 AuthenticationStateProvider 에 "state"라는 단어에도 불구하고 일반 사용자 상태를 저장하기 위한 것이 아닙니다. AuthenticationStateProvider 은 앱에 로그인했는지 여부와 로그인한 사용자 등 앱에 대한 사용자의 인증 상태만 나타냅니다.

인증은 Pages 및 MVC 앱과 동일한 ASP.NET Core Identity 인증 Razor 을 사용합니다. ASP.NET Core Identity에 대해 저장된 사용자 상태는 앱에 추가 코드를 작성하지 않고 Blazor로 전달됩니다. ASP.NET Core Identity 문서와 튜토리얼의 Identity 지침을 따라 앱의 Blazor 부분에서 기능이 작동하도록 하세요.

ASP.NET Core Identity외부의 일반 상태 관리에 대한 지침은 ASP.NET Core Blazor 상태 관리 개요를 참조하세요.

추가 보안 추상화

인증 상태 관리에는 두 가지 추가 추상화가 참여합니다.

Note

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

.NET 8 이상용 프로젝트 템플릿에서 생성된 앱에서 Blazor 기본 30분 유효성 재검사 간격을 조정합니다 IdentityRevalidatingAuthenticationStateProvider. .NET 8 이전 버전에서 간격을 조정합니다 RevalidatingIdentityAuthenticationStateProvider. 다음 예제에서는 간격을 20분으로 줄입니다.

protected override TimeSpan RevalidationInterval => TimeSpan.FromMinutes(20);

로그아웃 시 인증 상태 관리

서버 쪽 Blazor 은 브라우저 탭을 포함하여 회로의 수명 동안 사용자 인증 상태를 유지합니다. 사용자가 한 탭에서 로그아웃할 때 브라우저의 다른 탭에서도 사용자가 사전에 로그오프되도록 하려면, 짧은 RevalidatingServerAuthenticationStateProvider(참조 원본)을 구현 RevalidationInterval 해야 합니다.

Note

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

임시 리디렉션 URL 유효 기간

이 섹션은 s에 Blazor Web App적용됩니다.

RazorComponentsServiceOptions.TemporaryRedirectionUrlValidityDuration 옵션을 사용하여 Blazor 서버 쪽 렌더링에서 내보낸 임시 리디렉션 URL에 대한 ASP.NET Core Data Protection의 유효 기간을 설정하거나 가져옵니다. 이는 일시적으로만 사용되므로 클라이언트가 URL을 수신하고 탐색을 시작할 수 있을 만큼 수명만 길어야 합니다. 그러나 서버 간에 클록 기울이기를 허용할 만큼 길어야 합니다. 기본값은 5분입니다.

다음 예제에서는 값이 7분으로 확장됩니다.

builder.Services.AddRazorComponents(options => 
    options.TemporaryRedirectionUrlValidityDuration = 
        TimeSpan.FromMinutes(7));

클라이언트 쪽 Blazor 인증

클라이언트 쪽 Blazor 앱에서는 모든 클라이언트 쪽 코드를 사용자가 수정할 수 있으므로 클라이언트 쪽 인증 검사를 무시할 수 있습니다. JavaScript SPA 프레임워크 및 모든 운영 체제의 네이티브 앱을 비롯한 모든 클라이언트 쪽 앱 기술도 마찬가지입니다.

다음을 추가합니다.

인증을 처리하려면 기본 제공 또는 사용자 지정 AuthenticationStateProvider 서비스를 사용합니다.

클라이언트 쪽 인증에 대한 자세한 내용은 보안 ASP.NET Core를 참조하세요 Blazor WebAssembly.

대화형 자동 렌더링을 사용하여 Blazor Web App데이터 보호

Blazor Web App 구성 요소 또는 대화형 자동 렌더링 모드를 지정하는 전체 앱에 대해 SSR(서버 쪽 렌더링) 및 CSR(클라이언트 쪽 렌더링)을 채택하는 경우 구성 요소 및 데이터에 대한 액세스 권한 부여가 두 위치에 적용됩니다. 구성 요소는 구성 요소의 정의 파일(@attribute [Authorize])에 있는 권한 부여 특성을 통해 서버에서 렌더링될 때 자체(및 가져온 모든 데이터)에 대한 액세스를 제한합니다. 구성 요소가 클라이언트에서 렌더링되면 클라이언트에서 호출되는 서버 웹 API 엔드포인트를 통해 데이터에 대한 액세스가 제한됩니다. 부적절한 데이터 액세스를 방지하기 위해 두 위치에서 데이터 액세스를 보호하는 경우 주의해야 합니다.

구성 요소에서 보안 날씨 데이터를 표시하는 다음 시나리오를 고려합니다. 다음 방법 중 일부에 대한 데모는 샘플 BlazorWebAppEntra/BlazorWebAppEntraBffBlazorWebAppOidc샘플(.NET 8 이상)을 사용하여/BlazorWebAppOidcBffBlazor 평가 및 테스트dotnet/blazor-samples 수 있습니다.

클라이언트 프로젝트는 날씨 데이터를 저장할 WeatherForecast 클래스를 유지 관리합니다.

public sealed class WeatherForecast(DateOnly date, int temperatureC, string summary)
{
    public DateOnly Date { get; set; } = date;
    public int TemperatureC { get; set; } = temperatureC;
    public string? Summary { get; set; } = summary;
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}

클라이언트 프로젝트의 IWeatherForecaster 인터페이스는 날씨 데이터를 가져오기 위한 GetWeatherForecastAsync 메서드를 정의합니다.

public interface IWeatherForecaster
{
    Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync();
}

클라이언트 프로젝트의 ClientWeatherForecaster 서비스는 IWeatherForecaster구현합니다. GetWeatherForecastAsync 메서드는 날씨 데이터에 대한 /weather-forecast 엔드포인트의 서버 프로젝트에서 웹 API를 호출합니다.

internal sealed class ClientWeatherForecaster(HttpClient httpClient) 
    : IWeatherForecaster
{
    public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync() =>
        await httpClient.GetFromJsonAsync<WeatherForecast[]>("/weather-forecast") ??
            throw new IOException("No weather forecast!");
}

클라이언트 프로젝트는 다음과 같은 Weather 구성 요소를 유지 관리합니다.

@page "/weather"
@using Microsoft.AspNetCore.Authorization
@using BlazorWebAppEntra.Client.Weather
@attribute [Authorize]
@inject IWeatherForecaster WeatherForecaster

<PageTitle>Weather</PageTitle>

<h1>Weather</h1>

<p>This component demonstrates showing data.</p>

@if (Forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th aria-label="Temperature in Celsius">Temp. (C)</th>
                <th aria-label="Temperature in Fahrenheit">Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in Forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    [PersistentState]
    public IEnumerable<WeatherForecast>? Forecasts { get; set; }

    protected override async Task OnInitializedAsync()
    {
        Forecasts ??= await WeatherForecaster.GetWeatherForecastAsync();
    }
}
@page "/weather"
@using Microsoft.AspNetCore.Authorization
@using BlazorWebAppEntra.Client.Weather
@attribute [Authorize]
@implements IDisposable
@inject PersistentComponentState ApplicationState
@inject IWeatherForecaster WeatherForecaster

<PageTitle>Weather</PageTitle>

<h1>Weather</h1>

<p>This component demonstrates showing data.</p>

@if (forecasts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>Date</th>
                <th aria-label="Temperature in Celsius">Temp. (C)</th>
                <th aria-label="Temperature in Fahrenheit">Temp. (F)</th>
                <th>Summary</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var forecast in forecasts)
            {
                <tr>
                    <td>@forecast.Date.ToShortDateString()</td>
                    <td>@forecast.TemperatureC</td>
                    <td>@forecast.TemperatureF</td>
                    <td>@forecast.Summary</td>
                </tr>
            }
        </tbody>
    </table>
}

@code {
    private IEnumerable<WeatherForecast>? forecasts;
    private PersistingComponentStateSubscription persistingSubscription;

    protected override async Task OnInitializedAsync()
    {
        if (!ApplicationState.TryTakeFromJson<IEnumerable<WeatherForecast>>(
            nameof(forecasts), out var restoredData))
        {
            forecasts = await WeatherForecaster.GetWeatherForecastAsync();
        }
        else
        {
            forecasts = restoredData!;
        }

        // Call at the end to avoid a potential race condition at app shutdown
        persistingSubscription = ApplicationState.RegisterOnPersisting(PersistData);
    }

    private Task PersistData()
    {
        ApplicationState.PersistAsJson(nameof(forecasts), forecasts);

        return Task.CompletedTask;
    }

    void IDisposable.Dispose() => persistingSubscription.Dispose();
}

서버 프로젝트는 IWeatherForecasterServerWeatherForecaster로 구현하고, GetWeatherForecastAsync 메서드를 통해 날씨 데이터를 생성하고 반환합니다.

internal sealed class ServerWeatherForecaster() : IWeatherForecaster
{
    public readonly string[] summaries =
    [
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", 
        "Sweltering", "Scorching"
    ];

    public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync()
    {
        // Simulate asynchronous loading to demonstrate streaming rendering
        await Task.Delay(500);

        return Enumerable.Range(1, 5).Select(index =>
            new WeatherForecast
            (
                DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                Random.Shared.Next(-20, 55),
                summaries[Random.Shared.Next(summaries.Length)]
            ))
        .ToArray();
    }
}

앱이 날씨 데이터를 가져오기 위해 외부 웹 API를 호출해야 하는 경우 HTTP 클라이언트(HttpClient)를 삽입하여 데이터를 요청할 수 있습니다.

internal sealed class ServerWeatherForecaster(HttpClient httpClient, 
    IHttpContextAccessor httpContextAccessor) : IWeatherForecaster
{
    public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync()
    {
        var httpContext = httpContextAccessor.HttpContext ??
            throw new InvalidOperationException("No HttpContext!");
        var accessToken = await httpContext.GetTokenAsync("access_token") ??
            throw new InvalidOperationException("No access_token was saved");
        using var request = 
            new HttpRequestMessage(HttpMethod.Get, "/weather-forecast");
        request.Headers.Authorization = new("Bearer", accessToken);
        using var response = await httpClient.SendAsync(request);
        response.EnsureSuccessStatusCode();

        return await response.Content.ReadFromJsonAsync<WeatherForecast[]>() ??
            throw new IOException("No weather forecast!");
    }
}

또 다른 방법에서는 토큰 처리기와 함께 명명된 HTTP 클라이언트를 사용하여 HTTP 클라이언트 팩터리(IHttpClientFactory) ServerWeatherForecaster 를 삽입하고 외부 웹 API를 호출할 수 있습니다. 자세한 내용은 ASP.NET Core Blazor 앱에서 웹 API 호출을 참조하세요.

앱이 Microsoft Entra IDMicrosoft 웹 패키지와 함께 Microsoft IdentityID 플랫폼을 사용하는 경우(ASP.NET Core Blazor 앱에서 웹 API 호출 참조) 다음은 ServerWeatherForecaster 외부 웹 API 호출을 만드는 방법을 보여 줍니다. 액세스 토큰은 요청에 자동으로 연결됩니다.

internal sealed class ServerWeatherForecaster(IDownstreamApi downstreamApi) : IWeatherForecaster
{
    public async Task<IEnumerable<WeatherForecast>> GetWeatherForecastAsync()
    {
        using var response = await downstreamApi.CallApiForUserAsync("DownstreamApi",
            options =>
            {
                options.RelativePath = "/weather-forecast";
            });

        return await response.Content.ReadFromJsonAsync<WeatherForecast[]>() ??
            throw new IOException("No weather forecast!");
    }
}

데이터를 가져오기 위해 사용하는 ServerWeatherForecaster 접근 방식과 관계없이 서버 프로젝트는 클라이언트 날씨 데이터 호출에 대한 보안 웹 API 엔드포인트를 유지 관리합니다. 서버에서 이 엔드포인트는 ServerWeatherForecaster.GetWeatherForecastAsync 호출을 발생시킵니다.

app.MapGet("/weather-forecast", (
    [FromServices] IWeatherForecaster WeatherForecaster) =>
{
    return WeatherForecaster.GetWeatherForecastAsync();
}).RequireAuthorization();

위의 방법을 사용하여 사용자에게 안전한 날씨 데이터를 제공하는 두 가지 시스템이 있습니다.

  • Weather 구성 요소가 서버 렌더링되면 ServerWeatherForecaster 서비스의 GetWeatherForecastAsync 메서드를 사용하여 날씨 데이터를 직접 가져옵니다. 데이터의 보안은 구성 요소의 [Authorize] 특성에 의해 적용됩니다. 요약하자면, 날씨 데이터의 보안은 구성 요소에 의해 적용됩니다.
  • Weather 구성 요소가 클라이언트 렌더링되는 경우 ClientWeatherForecaster 서비스는 /weather-forecast 확장 메서드를 적용하는 보안 RequireAuthorization 엔드포인트에 대한 웹 API 호출을 만드는 데 사용됩니다. 사용자에게 날씨 데이터에 액세스할 권한이 있는 경우 엔드포인트는 ServerWeatherForecaster 서비스를 사용하여 GetWeatherForecastAsync호출합니다. 데이터가 클라이언트에 반환됩니다. 요약하면 날씨 데이터의 보안은 서버 앱의 웹 API 엔드포인트에 의해 적용됩니다.

앞의 방법은 웹 API의 보안 요구 사항이 구성 요소의 보안 요구 사항과 일치하는 경우 잘 작동합니다. 예를 들어 웹 API 엔드포인트와 구성 요소 모두에 동일한 권한 부여 정책을 적용할 수 있습니다.

복잡한 시나리오에는 추가 계획 및 구현이 필요합니다. 예를 들어 액세스 권한이 다른 여러 호출자가 있는 서버 웹 API에는 보다 정교한 권한 부여 정책, 하나 이상의 추가 정책 또는 다른 액세스 요구 사항이 있는 추가 엔드포인트가 필요합니다.

대화형 자동 렌더링을 채택하는 앱에 보안을 구축할 때 서버의 웹 API 엔드포인트에 대해 구현된 보안은 구성 요소가 서버에 렌더링되고 서비스를 통해 데이터에 액세스할 때 사용되는 서버의 서비스 구현을 보호하지 않는다는 점에 유의하세요. SSR 중에 서버의 데이터에 액세스하는 것과 CSR 중에 클라이언트 웹 API 요청의 데이터에 액세스하는 것 사이의 차이점을 신중하게 측정합니다. 데이터에 대한 부적절한 액세스를 방지하기 위해 보안을 전략적으로 적용합니다.

이 섹션에 설명된Blazordotnet/blazor-samples 방법을 보여 주는 샘플 GitHub 리포지토리()(다운로드 방법)의 예:

  • BlazorWebAppOidc
  • BlazorWebAppOidcBff
  • BlazorWebAppEntra
  • BlazorWebAppEntraBff

AuthenticationStateProvider 서비스

AuthenticationStateProvider 는 구성 요소 및 연계 인증 서비스에서 사용자의 인증 상태를 가져오는 데 사용하는 AuthorizeView 기본 서비스입니다.

AuthenticationStateProviderAuthorizeView 구성 요소 및 CascadingAuthenticationState 구성 요소가 사용자의 인증 상태를 가져오기 위해 사용하는 기본 서비스입니다.

일반적으로 AuthenticationStateProvider를 직접 사용하지는 않습니다. 이 문서의 뒷부분에서 AuthorizeView 설명하는 구성 요소 또는 Task<AuthenticationState> 접근 방식을 사용합니다. AuthenticationStateProvider를 직접 사용하는 경우의 주요 단점은 기본 인증 상태 데이터가 변경될 때 구성 요소가 자동으로 알림을 받지 못하는 것입니다.

사용자 지정 AuthenticationStateProvider를 구현하려면, 사용자 인증 상태 변경 알림 구현에 대한 지침을 포함한 ASP.NET Core Blazor 인증 상태를 참조하세요.

사용자의 클레임 데이터 가져오기

서비스는 AuthenticationStateProvider 다음 예제와 같이 현재 사용자의 ClaimsPrincipal 데이터를 제공할 수 있습니다.

ClaimsPrincipalData.razor:

@page "/claims-principal-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>ClaimsPrincipal Data</h1>

<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>

<p>@authMessage</p>

@if (claims.Any())
{
    <ul>
        @foreach (var claim in claims)
        {
            <li>@claim.Type: @claim.Value</li>
        }
    </ul>
}

<p>@surname</p>

@code {
    private string? authMessage;
    private string? surname;
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider
            .GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity is not null && user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
            claims = user.Claims;
            surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

앞의 예에서:

  • ClaimsPrincipal.Claims 는 UI에 표시할 사용자의 클레임(claims)을 반환합니다.
  • 사용자의 성(surname)을 가져오는 문장은 조건자를 사용하여 사용자의 클레임을 필터링하기 위해 ClaimsPrincipal.FindAll을(를) 호출합니다.
@page "/claims-principal-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>ClaimsPrincipal Data</h1>

<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>

<p>@authMessage</p>

@if (claims.Any())
{
    <ul>
        @foreach (var claim in claims)
        {
            <li>@claim.Type: @claim.Value</li>
        }
    </ul>
}

<p>@surname</p>

@code {
    private string? authMessage;
    private string? surname;
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider
            .GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity is not null && user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
            claims = user.Claims;
            surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

user.Identity.IsAuthenticatedtrue이면, 사용자가 ClaimsPrincipal이므로 클레임을 열거하고 역할의 멤버 자격을 평가할 수 있습니다.

DI(종속성 주입) 및 서비스에 대한 자세한 내용은 Blazor 및 ASP.NET Core의 종속성 주입을 참조하세요. 사용자 지정 AuthenticationStateProvider을 구현하는 방법에 대한 자세한 내용은 ASP.NET Core Blazor 인증 상태를 참조하세요.

인증 상태를 연계 매개 변수로 공개

인증 상태 데이터가 절차 논리에 필요하다면, 예를 들어 사용자가 트리거하는 작업을 수행할 때처럼, 다음 예제와 같이 Task<AuthenticationState 형식의 > 캐스케이딩 매개 변수를 정의하여 인증 상태 데이터를 가져옵니다.

CascadeAuthState.razor:

@page "/cascade-auth-state"

<h1>Cascade Auth State</h1>

<p>@authMessage</p>

@code {
    private string authMessage = "The user is NOT authenticated.";

    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user?.Identity is not null && user.Identity.IsAuthenticated)
            {
                authMessage = $"{user.Identity.Name} is authenticated.";
            }
        }
    }
}
@page "/cascade-auth-state"

<h1>Cascade Auth State</h1>

<p>@authMessage</p>

@code {
    private string authMessage = "The user is NOT authenticated.";

    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user?.Identity is not null && user.Identity.IsAuthenticated)
            {
                authMessage = $"{user.Identity.Name} is authenticated.";
            }
        }
    }
}

user.Identity.IsAuthenticatedtrue이면, 클레임을 열거하고 역할의 멤버 자격을 평가할 수 있습니다.

Task< AuthenticationState > 연계 매개 변수AuthorizeRouteView 및 연계 인증 상태 서비스를 사용하여 설정합니다.

인증이 사용 설정된 프로젝트 템플릿 중 하나인 Blazor에서 앱을 생성할 때, 앱에는 다음 예제에 나오는 Blazor와 AuthorizeRouteView 호출을 포함합니다. 클라이언트 쪽 Blazor 앱에는 필요한 서비스 등록도 포함됩니다. 추가 정보는 Router 구성 요소를 사용하여 권한 없는 콘텐츠 사용자 지정 섹션에서 제시됩니다.

<Router ...>
    <Found ...>
        <AuthorizeRouteView RouteData="routeData" 
            DefaultLayout="typeof(Layout.MainLayout)" />
        ...
    </Found>
</Router>

파일에서 Program 계층적 인증 상태 서비스를 등록합니다.

builder.Services.AddCascadingAuthenticationState();

Task<AuthenticationState 구성 요소를 사용하여 >AuthorizeRouteViewCascadingAuthenticationState를 설정합니다.

인증이 사용 설정된 Blazor 프로젝트 템플릿 중 하나에서 Blazor 앱을 만들면, 앱에는 다음 예제에 표시된 AuthorizeRouteViewCascadingAuthenticationState 구성 요소가 포함됩니다. 클라이언트 쪽 Blazor 앱에는 필요한 서비스 등록도 포함됩니다. 추가 정보는 Router 구성 요소를 사용하여 권한 없는 콘텐츠 사용자 지정 섹션에서 제시됩니다.

<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView RouteData="routeData" 
                DefaultLayout="typeof(MainLayout)" />
            ...
        </Found>
    </Router>
</CascadingAuthenticationState>

Note

.NET 5.0.1 릴리스 및 추가 5.x 릴리스의 경우, Router 구성 요소에는 PreferExactMatches 매개 변수가 @true로 설정됩니다. 자세한 내용은 ASP.NET Core 3.1에서 .NET 5로 마이그레이션을 참조하세요.

클라이언트 쪽 Blazor 앱에서 권한 부여 서비스를 파일에 추가합니다.Program

builder.Services.AddAuthorizationCore();

클라이언트 쪽 Blazor 앱에서 옵션 및 권한 부여 서비스를 파일에 추가합니다 Program .

builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();

서버 쪽 Blazor 앱에서는 옵션 및 권한 부여에 대한 서비스가 이미 있으므로 추가 단계가 필요하지 않습니다.

Authorization

사용자가 인증되면, 사용자가 수행할 수 있는 작업을 제어하기 위해 ‘권한 부여’ 규칙이 적용됩니다.

일반적으로 다음 여부에 따라 액세스가 허용 또는 거부됩니다.

  • 사용자가 인증(로그인)되었는지 여부
  • 사용자가 역할에 있습니다.
  • 사용자에게 ‘클레임’이 있는지 여부
  • 정책이 충족됩니다.

이러한 각 개념은 ASP.NET Core MVC 또는 Razor Pages 앱에서와 동일합니다. ASP.NET Core 보안에 대한 자세한 내용은 ASP.NET Core 보안 및 Identity아래 문서를 참조하세요.

AuthorizeView 구성 요소

AuthorizeView 구성 요소는 사용자에게 권한이 있는지에 따라 선택적으로 UI 콘텐츠를 표시합니다. 이 방법은 사용자의 데이터를 표시해야 하며 절차 논리에서 사용자의 ID를 사용할 필요가 없는 경우에 유용합니다.

구성 요소는 context 형식의 AuthenticationState 변수(@context 구문에서 Razor)를 노출하며, 이를 사용하여 로그인한 사용자에 대한 정보를 액세스할 수 있습니다.

<AuthorizeView>
    <p>Hello, @context.User.Identity?.Name!</p>
</AuthorizeView>

사용자에게 다음과 같은 매개 변수의 조합 AuthorizedNotAuthorized 으로 권한이 부여되지 않은 경우 표시할 다른 콘텐츠를 제공할 수도 있습니다.

<AuthorizeView>
    <Authorized>
        <p>Hello, @context.User.Identity?.Name!</p>
        <p><button @onclick="HandleClick">Authorized Only Button</button></p>
    </Authorized>
    <NotAuthorized>
        <p>You're not authorized.</p>
    </NotAuthorized>
</AuthorizeView>

@code {
    private void HandleClick() { ... }
}

AuthorizeView 구성 요소는 사용자의 권한 부여 상태에 따라 요소의 표시 유형을 제어하지만 이벤트 처리기 자체에 보안을 적용하지는 않습니다. 앞의 예제 HandleClick 에서 메서드는 권한 있는 사용자에게 표시되는 단추와만 연결되지만 다른 위치에서 이 메서드를 호출하는 것을 방지하는 것은 없습니다. 메서드 수준 보안을 보장하려면 처리기 자체 또는 관련 API 내에서 추가 권한 부여 논리를 구현합니다.

Razor Blazor Web App의 구성 요소는 SSR(서버 쪽 렌더링) 중에 서버에서 권한 부여가 실패한 경우에 <NotAuthorized> 콘텐츠를 표시하지 않습니다. 서버 쪽 ASP.NET Core 파이프라인은 서버에서 권한 부여를 처리합니다. 서버 쪽 기술을 사용하여 권한 없는 요청을 처리합니다. 자세한 내용은 ASP.NET Core Blazor 렌더링 모드를 참조하세요.

Warning

클라이언트 쪽 AuthorizeView와 관련된 태그와 메서드는 클라이언트 쪽 앱의 렌더링된 UI에서 보기와 실행으로부터만 보호됩니다. 클라이언트 쪽 Blazor에서 권한 있는 콘텐츠 및 보안 메서드를 보호하기 위해 콘텐츠는 일반적으로 서버 API에 대한 안전하고 권한이 부여된 웹 API 호출에 의해 제공되며 앱에 저장되지 않습니다. 자세한 내용은 ASP.NET Core 앱에서 웹 API 호출 및 추가 보안 시나리오를 참조하세요.

AuthorizedNotAuthorized의 콘텐츠에는 다른 대화형 구성 요소와 같은 임의 항목이 포함될 수 있습니다.

UI 옵션 또는 액세스를 제어하는 역할 또는 정책과 같은 권한 부여 조건은 권한 부여 섹션에서 다룹니다.

권한 부여 조건이 지정 AuthorizeView 되지 않은 경우 기본 정책을 사용합니다.

  • 인증된(로그인) 사용자에게 권한이 부여됩니다.
  • 인증되지 않은(로그아웃) 사용자는 권한이 없습니다.

AuthorizeView 구성 요소는 NavMenu 구성 요소(Shared/NavMenu.razor)에서 NavLink 구성 요소 (NavLink)를 표시하기 위해 사용할 수 있지만, 이 방법은 렌더링된 출력에서 목록 항목만 제거합니다. 사용자가 해당 구성 요소로 이동하는 것을 방지하지는 않습니다. 대상 구성 요소에서 별도로 권한 부여를 구현합니다.

역할 기반 및 정책 기반 권한 부여

AuthorizeView 구성 요소는 ‘역할 기반’ 또는 ‘정책 기반’ 권한 부여를 지원합니다.

역할 기반 권한 부여의 경우 Roles 매개 변수를 사용합니다. 사용자는 Admin 또는 Superuser 역할에 대한 역할 클레임이 있어야 합니다.

<AuthorizeView Roles="Admin, Superuser">
    <p>You have an 'Admin' or 'Superuser' role claim.</p>
</AuthorizeView>

사용자에게 Admin 역할 클레임과 Superuser 역할 클레임이 모두 필요할 때는 AuthorizeView 구성 요소들을 중첩하세요.

<AuthorizeView Roles="Admin">
    <p>User: @context.User</p>
    <p>You have the 'Admin' role claim.</p>
    <AuthorizeView Roles="Superuser" Context="innerContext">
        <p>User: @innerContext.User</p>
        <p>You have both 'Admin' and 'Superuser' role claims.</p>
    </AuthorizeView>
</AuthorizeView>

앞의 코드는 컨텍스트 충돌을 방지하기 위해 내부 Context 구성 요소에 대한 값을 AuthorizeView 설정합니다AuthenticationState. AuthenticationState 외부에서 AuthorizeView 컨텍스트를 접근하기 위해 표준 접근 방식(@context.User)을 사용합니다. 내부 AuthorizeView에서 명명된 innerContext 컨텍스트(@innerContext.User)로 컨텍스트에 액세스됩니다.

구성 지침을 비롯한 자세한 내용은 ASP.NET Core의 역할 기반 권한 부여를 참조하세요.

정책 기반 권한 부여의 Policy 경우 단일 정책 이름으로 매개 변수를 사용합니다.

<AuthorizeView Policy="Over21">
    <p>You satisfy the 'Over21' policy.</p>
</AuthorizeView>

사용자가 여러 정책 중 하나를 충족해야 하는 경우를 처리하려면 사용자가 다른 정책을 충족하는지 확인하는 정책을 만듭니다.

사용자가 여러 정책을 동시에 충족해야 하는 경우를 처리하려면 다음 방법 중 하나를 수행합니다.

  • 사용자가 여러 다른 정책을 충족하는지 확인하는 AuthorizeView 정책을 만듭니다.

  • 정책을 여러 AuthorizeView 구성 요소에 중첩합니다.

    <AuthorizeView Policy="Over21">
        <AuthorizeView Policy="LivesInCalifornia">
            <p>You satisfy the 'Over21' and 'LivesInCalifornia' policies.</p>
        </AuthorizeView>
    </AuthorizeView>
    

클레임 기반 권한 부여는 정책 기반 권한 부여의 특별한 경우입니다. 예를 들어 사용자에게 특정 클레임이 있어야 하는 정책을 정의할 수 있습니다. 자세한 내용은 ASP.NET Core의 정책 기반 권한 부여를 참조하세요.

둘 다 RolesPolicy 설정되면 두 조건이 모두 충족되는 경우에만 권한 부여가 성공합니다. 즉, 사용자는 지정된 역할 중 하나 이상에 속 해야 하며 정책에 정의된 요구 사항을 충족해야 합니다.

RolesPolicy 중 어느 것도 지정되지 않으면 AuthorizeView는 기본 정책을 사용합니다.

  • 인증된(로그인) 사용자에게 권한이 부여됩니다.
  • 인증되지 않은(로그아웃) 사용자는 권한이 없습니다.

.NET 문자열 비교는 대/소문자를 구분하므로 일치하는 역할 및 정책 이름도 대/소문자를 구분합니다. 예를 들어, Admin(대문자 A)는 admin(소문자 a)와 동일한 역할로 처리되지 않습니다.

파스칼 표기법은 일반적으로 역할 및 정책 이름(예: BillingAdministrator)에 사용되지만, 파스칼 표기법을 사용하는 것은 필수는 아닙니다. 낙타 케이스, 케밥 케이스 및 뱀 케이스와 같은 다양한 대/소문자 구성표가 허용됩니다. 역할 및 정책 이름에 공백을 사용하는 것은 비정상적이지만 프레임워크에서 허용됩니다. 예를 들어 billing administrator .NET 앱에서 비정상적인 역할 또는 정책 이름 형식이지만 유효한 역할 또는 정책 이름입니다.

비동기 인증 중에 표시되는 콘텐츠

Blazor 을 사용하면 인증 상태를 비동기적으로 확인할 수 있습니다. 이 방법의 기본 시나리오는 인증을 위해 외부 엔드포인트에 요청을 하는 클라이언트 쪽 Blazor 앱에 있습니다.

인증이 진행 중인 AuthorizeView 동안에는 콘텐츠가 표시되지 않습니다. 인증이 발생하는 동안 콘텐츠를 표시하려면 매개 변수에 Authorizing 콘텐츠를 할당합니다.

<AuthorizeView>
    <Authorized>
        <p>Hello, @context.User.Identity?.Name!</p>
    </Authorized>
    <Authorizing>
        <p>You can only see this content while authentication is in progress.</p>
    </Authorizing>
</AuthorizeView>

이 방법은 일반적으로 서버 쪽 Blazor 앱에 적용되지 않습니다. 서버 쪽 Blazor 앱은 상태가 설정되는 즉시 인증 상태를 알고 있습니다. Authorizing 콘텐츠는 앱의 AuthorizeView 구성 요소에 제공할 수 있지만 콘텐츠는 표시되지 않습니다.

[Authorize] 특성

특성은 구성 요소에서 사용할 수 있습니다.

@page "/"
@attribute [Authorize]

You can only see this if you're signed in.

Important

라우터를 통해 도달한 [Authorize] 구성 요소에서만 @page를 사용합니다. 권한 부여는 라우팅의 일부로만 수행되고, 페이지에 렌더링된 자식 구성 요소에 대해서는 수행되지 ‘않습니다’. 페이지 내의 특정 파트 표시 권한을 부여하려면 AuthorizeView를 대신 사용합니다.

이 특성은[Authorize] 역할 기반 또는 정책 기반 권한 부여도 지원합니다. 역할 기반 권한 부여의 경우 Roles 매개 변수를 사용합니다.

@page "/"
@attribute [Authorize(Roles = "Admin, Superuser")]

<p>You can only see this if you're in the 'Admin' or 'Superuser' role.</p>

정책 기반 권한 부여의 경우 Policy 매개 변수를 사용합니다.

@page "/"
@attribute [Authorize(Policy = "Over21")]

<p>You can only see this if you satisfy the 'Over21' policy.</p>

RolesPolicy 중 어느 것도 지정되지 않으면 [Authorize]는 기본 정책을 사용합니다.

  • 인증된(로그인) 사용자에게 권한이 부여됩니다.
  • 인증되지 않은(로그아웃) 사용자는 권한이 없습니다.

사용자에게 권한이 부여되지 않고 앱이 구성 요소로 Router 권한이 없는 콘텐츠를 사용자 지정하지 않으면 프레임워크에서 다음 대체 메시지를 자동으로 표시합니다.

Not authorized.

리소스 권한 부여

사용자에게 리소스에 대한 권한을 부여하려면 요청의 경로 데이터를 ResourceAuthorizeRouteView 매개 변수에 전달합니다.

요청된 경로의 Router.Found 콘텐츠에서:

<AuthorizeRouteView Resource="routeData" RouteData="routeData" 
    DefaultLayout="typeof(MainLayout)" />

권한 부여 상태 데이터가 전달되고 절차 논리에서 사용되는 방법에 대한 자세한 내용은 인증 상태를 연계 매개 변수 섹션으로 노출 섹션을 참조하세요.

AuthorizeRouteView에서 리소스에 대한 경로 데이터를 수신하면 권한 부여 정책에서 RouteData.PageTypeRouteData.RouteValues에 액세스하여 권한 부여 결정을 내리기 위한 사용자 지정 논리를 허용합니다.

다음 예제에서는 다음 논리를 사용하여 앱의 권한 부여 서비스 구성(EditUser)에 대해 AuthorizationOptions 정책을 AddAuthorizationCore에서 만듭니다.

  • 키가 id인 경로 값이 있는지 여부를 확인합니다. 키가 있는 경우 경로 값은 value에 저장됩니다.
  • id라는 변수에서 value를 문자열로 저장 거나 빈 문자열 값(string.Empty)을 설정합니다.
  • id가 빈 문자열이 아닌 경우에는 문자열의 값이 true로 시작되는 경우 정책이 충족됨(EMP 반환)을 어설션합니다. 그렇지 않은 경우 정책이 실패함(false 반환)을 어설션합니다.

Program 파일에서:

  • 다음과 같이 Microsoft.AspNetCore.ComponentsSystem.Linq의 네임스페이스를 추가합니다.

    using Microsoft.AspNetCore.Components;
    using System.Linq;
    
  • 다음과 같이 정책을 추가합니다.

    options.AddPolicy("EditUser", policy =>
        policy.RequireAssertion(context =>
        {
            if (context.Resource is RouteData rd)
            {
                var routeValue = rd.RouteValues.TryGetValue("id", out var value);
                var id = Convert.ToString(value, 
                    System.Globalization.CultureInfo.InvariantCulture) ?? string.Empty;
    
                if (!string.IsNullOrEmpty(id))
                {
                    return id.StartsWith("EMP", StringComparison.InvariantCulture);
                }
            }
    
            return false;
        })
    );
    

앞의 예제는 작업 예제를 사용하여 개념을 설명하는 데만 사용되는 너무 단순해진 권한 부여 정책입니다. 권한 부여 정책을 만들고 구성하는 방법에 대한 자세한 내용은 ASP.NET Core의 정책 기반 권한 부여를 참조하세요.

다음 EditUser 구성 요소에서 /users/{id}/edit의 리소스에는 사용자의 식별자({id})에 대한 경로 매개 변수가 있습니다. 구성 요소는 위의 EditUser 권한 부여 정책을 사용하여 id의 경로 값이 EMP로 시작하는지 여부를 확인합니다. idEMP로 시작하면 정책이 성공하고 구성 요소에 대한 액세스 권한이 부여됩니다. idEMP 이외의 값으로 시작하거나 id가 빈 문자열인 경우 정책이 실패하고 구성 요소가 로드되지 않습니다.

EditUser.razor:

@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]

<h1>Edit User</h1>

<p>The "EditUser" policy is satisfied! <code>Id</code> starts with 'EMP'.</p>

@code {
    [Parameter]
    public string? Id { get; set; }
}
@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]

<h1>Edit User</h1>

<p>The "EditUser" policy is satisfied! <code>Id</code> starts with 'EMP'.</p>

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

Router 구성 요소를 사용하여 권한 없는 콘텐츠를 사용자 지정하십시오.

Router 구성 요소와 함께 AuthorizeRouteView 구성 요소를 사용하면 다음과 같은 경우 앱이 사용자 지정 콘텐츠를 지정할 수 있습니다.

  • 사용자가 구성 요소에 적용된 [Authorize] 조건을 충족하지 못하는 경우 <NotAuthorized> 요소의 태그가 표시됩니다. 특성 [Authorize][Authorize] 특성 섹션에서 다룹니다.
  • 비동기 권한 부여가 진행 중이며 이는 일반적으로 사용자를 인증하는 프로세스가 진행되고 있음을 의미합니다. <Authorizing> 요소의 태그가 표시됩니다.

Important

Blazor 라우터 기능은 정적 서버 사이드 렌더링(SSR) 중에는 <NotAuthorized><NotFound> 콘텐츠를 표시하지 않으며 작동하지 않습니다. 요청 처리는 ASP.NET Core 미들웨어 파이프라인에 의해 완전히 처리되며, 무단 또는 잘못된 요청에 대해서는 Razor 구성 요소가 전혀 렌더링되지 않습니다. 서버 쪽 기술을 사용하여 정적 SSR 중에 무단 및 잘못된 요청을 처리합니다. 자세한 내용은 ASP.NET Core Blazor 렌더링 모드를 참조하세요.

<Router ...>
    <Found ...>
        <AuthorizeRouteView ...>
            <NotAuthorized>
                ...
            </NotAuthorized>
            <Authorizing>
                ...
            </Authorizing>
        </AuthorizeRouteView>
    </Found>
</Router>

AuthorizedNotAuthorized의 콘텐츠에는 다른 대화형 구성 요소와 같은 임의 항목이 포함될 수 있습니다.

Note

그러려면 앱의 Program 파일에서 계단식 인증 상태 서비스 등록이 필요합니다.

builder.Services.AddCascadingAuthenticationState();
<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView ...>
                <NotAuthorized>
                    ...
                </NotAuthorized>
                <Authorizing>
                    ...
                </Authorizing>
            </AuthorizeRouteView>
        </Found>
    </Router>
</CascadingAuthenticationState>

NotFound, AuthorizedNotAuthorized의 콘텐츠에는 다른 대화형 구성 요소와 같은 임의 항목이 포함될 수 있습니다.

콘텐츠가 지정 NotAuthorized 되지 않은 경우 AuthorizeRouteView 다음 대체 메시지를 사용합니다.

Not authorized.

인증이 활성화된 Blazor WebAssembly 프로젝트 템플릿에서 생성된 앱에는 RedirectToLogin 구성 요소의 콘텐츠에 위치한 <NotAuthorized> 구성 요소가 포함됩니다. 사용자가 인증되지 않은 경우(context.User.Identity?.IsAuthenticated != true) RedirectToLogin 구성 요소는 인증을 위해 브라우저를 authentication/login 엔드포인트로 리디렉션합니다. 사용자는 ID 공급자를 인증한 후 요청된 URL로 돌아갑니다.

절차적 논리

앱이 절차적 논리의 일부로 권한 부여 규칙을 확인해야 하는 경우, Task<AuthenticationState> 형식의 연계 매개 변수를 사용하여 사용자의 ClaimsPrincipal을 가져옵니다. Task< 등의 다른 서비스와 AuthenticationState>IAuthorizationService를 결합하여 정책을 평가할 수 있습니다.

다음 예제에서

  • user.Identity.IsAuthenticated 인증된(로그인) 사용자에 대한 코드를 실행합니다.
  • ' user.IsInRole("admin") 관리자' 역할의 사용자에 대한 코드를 실행합니다.
  • (await AuthorizationService.AuthorizeAsync(user, "content-editor")).Succeeded는 'content-editor' 정책을 만족하는 사용자를 위한 코드를 실행합니다.

서버 쪽 Blazor 앱은 프로젝트 템플릿에서 만들 때 적절한 네임스페이스를 포함합니다. 클라이언트 쪽 Blazor 앱에서, 구성 요소 또는 앱의 Microsoft.AspNetCore.Authorization 파일에 Microsoft.AspNetCore.Components.Authorization_Imports.razor 네임스페이스가 있는지 확인하십시오.

@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization

ProceduralLogic.razor:

@page "/procedural-logic"
@inject IAuthorizationService AuthorizationService

<h1>Procedural Logic Example</h1>

<button @onclick="@DoSomething">Do something important</button>

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

    private async Task DoSomething()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user is not null)
            {
                if (user.Identity is not null && user.Identity.IsAuthenticated)
                {
                    // ...
                }

                if (user.IsInRole("Admin"))
                {
                    // ...
                }

                if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
                    .Succeeded)
                {
                    // ...
                }
            }
        }
    }
}
@page "/procedural-logic"
@inject IAuthorizationService AuthorizationService

<h1>Procedural Logic Example</h1>

<button @onclick="@DoSomething">Do something important</button>

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

    private async Task DoSomething()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user is not null)
            {
                if (user.Identity is not null && user.Identity.IsAuthenticated)
                {
                    // ...
                }

                if (user.IsInRole("Admin"))
                {
                    // ...
                }

                if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
                    .Succeeded)
                {
                    // ...
                }
            }
        }
    }
}

오류 해결

일반 오류:

  • 권한을 부여하려면 Task<AuthenticationState> 형식의 연계 매개 변수가 필요합니다. CascadingAuthenticationState를 사용하여 이 변수를 제공하는 방법을 고려하세요.

  • null 에 대한 값이 수신됩니다. authenticationStateTask

인증을 사용하도록 설정된 서버 쪽 Blazor 템플릿을 사용하여 프로젝트를 만들지 않았을 수 있습니다.

.NET 7 또는 이전 버전에서는 UI 트리의 일부, 예를 들어 <CascadingAuthenticationState> 라우터 주위를 Blazor로 래핑합니다.

<CascadingAuthenticationState>
    <Router ...>
        ...
    </Router>
</CascadingAuthenticationState>

.NET 8 이상에서는 다음 구성 요소를 사용하지 CascadingAuthenticationState 마세요.

- <CascadingAuthenticationState>
      <Router ...>
          ...
      </Router>
- </CascadingAuthenticationState>

대신 파일의 서비스 컬렉션 Program 에 연계 인증 상태 서비스를 추가합니다.

builder.Services.AddCascadingAuthenticationState();

CascadingAuthenticationState 구성 요소(.NET 7 이하) 또는 AddCascadingAuthenticationState 서비스(.NET 8 이상)에서는 기본 Task< 종속성 주입 서비스에서 수신한 AuthenticationState>AuthenticationStateProvider 연계 매개 변수를 제공합니다.

PII(개인 식별 정보)

Microsoft는 설명서에서 PII (개인 식별 정보)에 대해 설명하는 경우 '개인 데이터'(GDPR 4.1)에 GDPR 정의를 사용합니다.

PII는 식별되거나 식별 가능한 자연인과 관련된 모든 정보를 참조합니다. 식별 가능한 자연인은 다음 중 하나를 사용하여 직접 또는 간접적으로 식별할 수 있는 사람입니다.

  • Name
  • 식별 번호
  • 위치 좌표
  • 온라인 식별자
  • 기타 특정 요소
    • Physical
    • Physiological
    • Genetic
    • 정신(심리적)
    • Economic
    • Cultural
    • 사회적 정체성

추가 리소스