在服务器端Blazor中实施认证和授权
今天,有许多网站提供重要的服务。为了开展这项工作,他们需要保护他们的网站不受不道德用户的影响。这就导致了在他们的网站上引入认证和授权。
认证是验证用户或进程的身份的过程或行动。每个设备的用户认证确保公司识别使用该设备的个人,而授权给予用户访问服务的权限。
在本教程中,我们将讨论认证和授权是如何在功能层中实现的。
有三个不同的基本层。
- 用户界面(UI)层
- 功能层
- 对象关系映射/数据库
先决条件
要完成本教程,我们需要。
- 安装[Visual Studio]。
- 对[C#]的基本了解
- 对[Blazor]的基本了解
开始学习
我们将首先创建一个服务器端的Blazor应用程序。为此,我们将打开Microsoft Visual Studio并选择Create a New Project 。

在下一个屏幕上,我们将选择Blazor server App ,然后点击Next 。

在下一个屏幕上,我们需要配置我们的新项目,我们将输入项目的名称并点击Next 。

在下一个屏幕上,我们将选择.NET Core 3.1 (Long-term support) 作为我们的目标框架,然后点击Create 。

用户界面
这是用户与之互动的一层。它使用户能够注册、登录、恢复密码和管理用户资料。
功能层
这一层是用来验证和授权用户信息的。在我们的项目中,我们将在这一层工作,实现授权功能。
为了开始我们的认证功能,我们将进入startup.cs 文件,在configure 方法中,在else语句后添加以下代码,以启用认证和授权。
app.UseAuthentication();
app.UseAuthorization();
在下一步,我们将添加一个认证状态提供者,它将为我们提供用户的状态。要做到这一点,我们将在我们的数据文件夹中添加一个名为AuthStateProvider 的类。
现在在创建的类中,为了返回硬编码用户的认证状态,例如,johndoe@gmail.com ,因为没有用户登录到系统中,我们将使用下面的代码。
namespace ServerApp.Data
{
public class NewAuthenticationStateProvider : AuthenticationStateProvider
{
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, "Johndoe@gmail.com"),
}, "apiauth_ype");
var user = new ClaimsPrincipal(identity);
return Task.FromResult(new AuthenticationState(user));
}
}
}
下一件事是在startup.cs 文件中添加认证状态提供者。这是在ConfigureServices 方法中完成的。
使用下面的代码行。
services.AddScoped<NewAuthenticationStateProvider, NewAuthenticationStateProvider>();
在上面的代码中,我们正在添加一个范围内的状态提供者的实例,并用NewAuthenticationStateProvider 。现在我们告诉应用程序路由,我们期待NewAuthenticationStateProvider ,作为级联参数,可以在整个应用程序中传递,我们可以使用它。
为了实现这一点,进入app.razor 文件,编辑这行代码<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> 到<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" /> 。AuthorizeRouteView 将状态提供者作为级联参数,可以在需要时使用。
我们将再次在<CascadingAuthenticationState> 中添加Not found 参数内的代码。这是两个将认证状态作为级联的状态。即
<NotFound>
<CascadingAuthenticationState>
<LayoutView Layout="@typeof(MainLayout)">
<p>Sorry, there's nothing at this address.</p>
</LayoutView>
</CascadingAuthenticationState>
</NotFound>
现在,在索引页上,我们需要在屏幕上显示认证用户的名字,如下所示。
<SurveyPrompt Title="How is Blazor working for you?" />
<AuthorizeView>
<Authorized>
<p>Hello @context.User.Identity.Name</p>
</Authorized>
<NotAuthorized>
<p>Please log in to access the page. Thank you</p>
</NotAuthorized>
</AuthorizeView>
@context.User.Identity.Name 是在用户成功登录时显示用户的名字。如果用户没有登录,他们将看到 。Please log in to access the page. Thank you
接下来,我们需要创建一个登录页面,使用户能够登录。要做到这一点,请到pages文件夹中,添加另一个页面。
打开该文件并添加以下代码。
@page "/login"
@Using ServerApp.Data
@code {
private User user;
protected ovveride Task OnInitializedAsync()
{
user = new User();
return base.OnInitializedAsync();
}
private async Task<bool> Validate User()
{
return await Task.FromResult(true);
}
}
现在,我们需要在用户被验证时改变状态,为了做到这一点,我们将在NewAuthenticationStateProvider 文件中创建一个函数,该函数接受一个字符串作为参数,并调用它UserAuthenticated ,然后将其发送到NotifyAuthenticationStateChanged 。这将告诉认证状态提供者,状态已经改变。
public void UserAuthenticated(string name)
{
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, "johndoe@gmail.com"),
}, "apiauth_ype");
var user = new ClaimsPrincipal(identity);
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
}
在login razor页面中,我们将使用下面的代码行注入AuthenticationStateProvider 。
@inject AuthenticationStateProvider AuthenticationStateProvider
当用户点击登录时,他们需要被标记为已认证,这是通过传入用户的电子邮件地址来完成的,如下面的代码。
((NewAuthenticationStateProvider)AuthenticationStateProvider).UserAuthenticated(user.EmailAddress);
用户现在需要从登录界面导航到索引页,所以你将在login.razor page ,即注入一个导航管理器。
@inject NavigationManger NavigationManager;
为了导航到主页,我们将使用下面这行代码。
NavigationManager.NavigateTo("/");
当我们刷新我们的浏览器时,我们注意到我们被签出了。为了确保我们没有被签出,我们将下载一个名为Blazored.SessionStorage 的NUGET 包,并将其添加到startup.cs 文件中。
services.AddBlazoredSessionStorage();
现在在登录页面,我们需要注入会话存储,如下图所示。
@inject Blazored.SessionStorage.ISessionStorageService sessionStorage
我们还将添加一个密钥,这个密钥将是用户的电子邮件地址,这样即使用户刷新浏览器,用户名也会被保存在会话存储中。要做到这一点,请在private async Task<bool> Validate User() 函数中添加以下代码。
await sessionStorage.setItemAsync("emailAddress", user.emailAdress);
现在,为了使用会话存储,在NewAuthenticationStateProvider 中写一个构造函数。
private ISessionStorageService _sessionStorageService;
public NewAuthenticationStateProvider(ISessionStorageService sessionStorageService)
{
_sessionStorageService = SessionStorageService;
}
现在我们有了会话状态提供者,当浏览器被刷新并且用户有一些值时,我们需要浏览器返回用户数据,否则就注销用户。这可以通过在public override Task<AuthenticationState> GetAuthenticationStateAsync() 函数中使用下面的代码来实现,并在每次刷新浏览器时调用它。
var emailAddress = await _sessionStorageService.GetItemAsync<string>(emailAddress);
ClaimsIdentity identity;
if(emailAddress != null)
{
identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, "emailAddress"),
}, "apiauth_ype");
}
else
{
identity = new ClaimsIdentity();
}
我们还需要告诉该函数它是一个异步函数,因为我们在上面的代码中使用了await 关键字。
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
通过添加await 关键字,将代码中的return Task.FromResult(true); 行改为return await Task.FromResult(true); 。最后要做的是实现注销功能。我们将导航到shared 文件夹,打开MainLayout.razor 文件,然后在div class ="main" 里面创建一个授权视图,即。
<AuthorizeView>
<Authorized>
<a href = "/login>" @onclick = "(() =>Logout())>Logout</a>
</Authorized>
<NotAuthorized>
<a href = "/login>">Login</a>
</NotAuthorized>
</AuthorizeView>
上面的代码基本上是告诉用户,如果他们没有登录,就要登录,如果他们已经登录了,就要注销。
我们将通过在NewAuthenticationStateProvider 中创建一个方法来实现注销功能,将用户标记为注销。即
public UserLoggedOut()
{
_sessionStorageService.RemoveItemAsync("emailAddresss");
var identity = new ClaimsIdentity();
var user = new ClaimsPrincipal(identity);
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
}
我们将需要在MainLayout.razor 页面中注入授权状态提供者。
@inject AuthenticationStateProvider AuthenticationStateProvider
在@code 部分添加下面的代码,标记用户为注销。
public void Logout()
{
((NewAuthenticaticationStateProvider)AuthenticationStateProvider).UserLoggedOut();
}
对象关系映射或数据库
该层存储、操作和更新用户信息。
总结
从这个教程中,我们了解到如何在blazor中实现服务器端授权,通过带你完成每一个步骤,易于理解和跟随。
注意: 项目中的任何错误都是通过导入必要的C#包来解决的。