Blazo身份认证授权示例以及如何对接统一登录平台

Blazo的身份认证授权示例以及如何对接统一登录平台

    在阅读本文之前,希望您已经对ASP.NET Core或者Web应用的身份认证机制有所了解。本文主要讲述Blazor WebAssembly模式下的身份认证和授权方法,以及页面元素访问控制,假如您对ASP.NET Core身份认证机制还不了解,可以查看该链接获取完整的sso——统一登录示例。

AuthorizeView 组件

AuthorizeView是blazor中用于身份认证的内置组件。


    

Hello, @context.User.Identity.Name!

You can only see this content if you're authenticated.

  • 在AuthorizeView组件包裹的代码段中,可以使用类型为 AuthenticationState的context变量,因此你可以获取到用户的名称,角色等内容。

  • AuthenticationState对象包含着用户身份信息,这个对象是由你自己创建出来的,AuthorizeView组件通过级联参数的形式来拿到。

  • 你可以通过实现自己的AuthenticationStateProvider 服务,来创建用户身份信息,即 ClaimsPrincipal 。

如何实现自己的AuthenticationStateProvider

如何实现一个具有登录/注销功能的Blazor应用呢?答案就是实现AuthenticationStateProvider服务。无论你是要对接已有的第三方统一登录平台,或是通过查询应用自身的用户数据库。

AuthenticationStateProvider类有一个方法需要你去重写:

Task GetAuthenticationStateAsync()

该方法是完成用户身份认证的唯一方法,你要重写它,并且用你自己的方式创造出一个包含认证信息的AuthenticationState对象。之后,你便可以在任何页面使用依赖注入获取一个Task< AuthenticationState>对象,并且AuthorizeView组件才能发挥作用。

在这里为大家附上一段实现示例:

 public override async Task GetAuthenticationStateAsync()
 {
         var principal = await GetUserPrincipalAsync();
         var authState = new AuthenticationState(principal);
         NotifyAuthenticationStateChanged(Task.FromResult(authState));
         return authState;
}

NotifyAuthenticationStateChanged回调函数是为了通知UI对象状态改变,其重点在于GetUserPrincipalAsync()方法,即如何获取用户身份令牌。

相信大家对用户身份令牌已经有所了解,令牌创建需要身份标识对象-ClaimsIdentity,标识则由一些Claim构成,Claim更像是标识了用户身份的键值对。通常我会使用ASP.NET Core中的ClaimTypes,来标识用户的名字,角色,id等。

下面给出一个通过HttpClient调用第三方登录接口的令牌获取示例

        private async Task GetUserPrincipalAsync()
        {
#if DEBUG
            return new ClaimsPrincipal(new ClaimsIdentity(new List()));
#endif
            var request = new HttpRequestMessage(HttpMethod.Get, "/login/Auth/UserInfo");
            request.SetBrowserRequestCredentials(BrowserRequestCredentials.Include);

            var response = await _serviceClient.SendAsync(request);
            if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                SignIn();
            }

            var content = await response.Content.ReadAsStringAsync();
            if (string.IsNullOrWhiteSpace(content))
            {
                return new ClaimsPrincipal(new ClaimsIdentity(new List()));
            }

            var userInfo = JsonConvert.DeserializeObject>(content).Result;

            return new ClaimsPrincipal(new ClaimsIdentity(new List
            {
                new Claim(ClaimTypes.Name, userInfo.Name),
                new Claim(ClaimTypes.NameIdentifier, userInfo.IdNumber)
            }));
        }

该登录接口会检查Http请求中是否带有cookie,token等身份信息,因此我创建了一个HttpRequestMessage对象,并且使用equest.SetBrowserRequestCredentials(BrowserRequestCredentials.Include); 方法来携带浏览器中该域名下的身份信息。 假如请求中存在用户身份信息,则返回用户姓名, Id等数据。然后根据返回数据创建身份令牌。

注意,这里有可能会出现跨域请求的现象,我会在后面的博客中讲述blazor单页应用如何避免这一问题。

假如请求中不存在用户信息,则需要调用SignIn();方法跳转到登录页面,该方法需要自己实现。这里也给出一个示例:

 public void SignIn(string customReturnUrl = null)
        {
            var returnUrl = customReturnUrl != null ? _navigationManager.ToAbsoluteUri(customReturnUrl).ToString() : null;

            var encodedReturnUrl = Uri.EscapeDataString(returnUrl ?? _navigationManager.Uri);

            var logInUrl = _navigationManager.ToAbsoluteUri($"{GetLoginPath()}?returnUrl={encodedReturnUrl}");

            _navigationManager.NavigateTo(logInUrl.ToString(), true);
        }

至于退出登录,则更简单了,调用退出接口并返回一个空的令牌即可:

public async Task SignOut(string customReturnUrl = null)
        {
            await _serviceClient.RequestAsync("/login/account/logout", HttpVerb.Get);

            _navigationManager.NavigateTo("/", true);

            var anonymousUser = new ClaimsPrincipal(new ClaimsIdentity());

            NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(anonymousUser)));
        }

看到这里你或许感到疑惑:你这里说的第三方登录平台是怎么实现的?我就想知道这个。本文主要讲述Blazor WebAssembly模式下的身份认证已经授权方法,假如您对ASP.NET Core身份认证机制还有所疑问,可以查看该链接获取完整的sso——统一登录示例。

我会在下篇博客讲述授权机制。

你可能感兴趣的:(Blazor,asp.net,core,blazor)