Visual Studio 在不使用AuthenticationStateProvider的情况下获取Blazor服务器应用中的当前用户

2jcobegt  于 2023-10-23  发布在  其他
关注(0)|答案(1)|浏览(114)

所以我刚刚开始了解blazor,我正试图使一个约会应用程序,在该应用程序中,我有一个页面,创建配置文件,但问题是,我不能让它读取登录的用户ID由它自己
这是我的代码

  1. @code {
  2. private string FullName { get; set; } = string.Empty;
  3. private DateTime Birthday { get; set; }
  4. private string Gender { get; set; } = "Male";
  5. private string City { get; set; } = string.Empty;
  6. private string PostalCode { get; set; } = string.Empty;
  7. private int Height { get; set; }
  8. private bool? ProfileCreated { get; set; }
  9. private string? ErrorMessage { get; set; }
  10. private string? isLoggedIn { get; set; }
  11. private int userId { get; set; }
  12. private async Task CreateProfileAsync()
  13. {
  14. try
  15. {
  16. int loggedInUserId = await GetCurrentLoggedInUserIdAsync(userId);
  17. bool success = await DatingAppService.CreateProfile(loggedInUserId, FullName, Birthday, Gender, City, PostalCode, Height);
  18. if (success)
  19. {
  20. ProfileCreated = true;
  21. ErrorMessage = string.Empty;
  22. Navigation.NavigateTo("/like-profile", forceLoad: true);
  23. }
  24. else
  25. {
  26. ProfileCreated = false;
  27. ErrorMessage = "Profile creation failed.";
  28. }
  29. }
  30. catch (Exception ex)
  31. {
  32. ProfileCreated = false;
  33. ErrorMessage = "An error occurred: " + ex.Message;
  34. }
  35. }
  36. private async Task<int> GetCurrentLoggedInUserIdAsync(int userId)
  37. {
  38. return userId;
  39. }
  40. private string ProfileStatusColor => ProfileCreated.Value ? "profile-success" : "profile-error";
  41. private string ProfileStatusMessage => ProfileCreated.Value ? "Profile created successfully!" : ErrorMessage;
  42. }

我尝试使用AuthenticationStateProvider,但它似乎不工作,因为我使用Blazor服务器应用程序。
请您客气点我是新手。

xdyibdwo

xdyibdwo1#

这个问题没有简短的答案。为了识别用户,您需要实现身份验证方案,然后与Blazor的AuthenticationStateProvider集成。
从阅读本系列文章开始:
https://chrissainty.com/series/securing-your-blazor-apps/
此外,官方文件在评论中指出:
https://learn.microsoft.com/en-us/aspnet/core/blazor/security
实际上,这里有几个主题可以彼此分开:
1.学习Blazor。
1.学习ASP.NET核心认证和授权。
1.学习如何将Blazor与AuthenticationStateProvider集成。
1.了解您可用的各种身份验证方案选项,例如Cookie、承载令牌、JWT等。
1.了解各种身份提供者,无论是本地(EF核心身份,相邻的Web API或数据库)还是外部(Azure,Auth 0,社交媒体平台等)。
作为一个初学者,你可能应该坚持使用一些应用内/本地身份验证提供程序,只是为了开始和熟悉一些基本的身份验证概念。应用内意味着,您可以使用本地数据库,可能是EF Core Identity数据库,而不是尝试与外部提供商集成。
最终,您用于学习/爱好项目目的的东西可能不会在真实的世界中飞行,当涉及到安全性和性能时,这取决于您的需求。
请注意,如果您发现自己编写了自己的哈希/加密算法来存储用户的敏感数据或密码,那么您就做错了。这可能不是你的项目的主要目的,你不应该试图发明已经存在的东西。
也许为了更直接地帮助您入门,请参阅此存储库--https://github.com/CodeFontana/BlazorSimpleAuthDemo
这是我能想到的最基本的用户身份验证演示,基于.NET 7.0的vanilla Blazor Server模板。
为了在Stack Overflow上回答的完整性,我将在这里发布代码的相关部分。
Program.cs

  1. using BlazorSimpleAuth.Authentication;
  2. using BlazorSimpleAuth.Data;
  3. using Microsoft.AspNetCore.Components.Authorization;
  4. WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
  5. builder.Services.AddRazorPages();
  6. builder.Services.AddServerSideBlazor();
  7. builder.Services.AddSingleton<WeatherForecastService>();
  8. builder.Services.AddScoped<IAuthenticationService, AuthenticationService>();
  9. builder.Services.AddScoped<AuthenticationStateProvider, SimpleAuthStateProvider>();
  10. WebApplication app = builder.Build();
  11. if (app.Environment.IsDevelopment() == false)
  12. {
  13. app.UseExceptionHandler("/Error");
  14. app.UseHsts();
  15. }
  16. app.UseHttpsRedirection();
  17. app.UseStaticFiles();
  18. app.UseRouting();
  19. app.UseAuthentication();
  20. app.UseAuthorization();
  21. app.MapBlazorHub();
  22. app.MapFallbackToPage("/_Host");
  23. app.Run();

App.razor:

  1. <CascadingAuthenticationState>
  2. <Router AppAssembly="@typeof(App).Assembly">
  3. <Found Context="routeData">
  4. <AuthorizeRouteView Context="AuthContext" RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" >
  5. <NotAuthorized>
  6. You are not authorized, please login.
  7. </NotAuthorized>
  8. </AuthorizeRouteView>
  9. </Found>
  10. <NotFound>
  11. <PageTitle>Not found</PageTitle>
  12. <LayoutView Layout="@typeof(MainLayout)">
  13. <p role="alert">Sorry, there's nothing at this address.</p>
  14. </LayoutView>
  15. </NotFound>
  16. </Router>
  17. </CascadingAuthenticationState>

Index.razor

  1. @page "/"
  2. @inject IAuthenticationService Auth
  3. <PageTitle>Index</PageTitle>
  4. <h1>Hello, world!</h1>
  5. Welcome to your new app.
  6. <AuthorizeView>
  7. <Authorized>
  8. <div class="mt-3">
  9. <p>Hello, @context.User.Identity!.Name!</p>
  10. <button type="submit" class="btn btn-primary" @onclick="OnLogout">
  11. <text>Logout</text>
  12. </button>
  13. </div>
  14. </Authorized>
  15. <NotAuthorized>
  16. <Login />
  17. </NotAuthorized>
  18. </AuthorizeView>
  19. @code {
  20. private void OnLogout()
  21. {
  22. // Logout user and update application state
  23. Auth.Logout();
  24. }
  25. }

Login.razor:

  1. @using System.Security.Claims;
  2. @inject NavigationManager Nav
  3. @inject IAuthenticationService Auth
  4. @inject AuthenticationStateProvider AuthState
  5. @attribute [AllowAnonymous]
  6. <div class="container mt-3">
  7. <div class="row d-flex justify-content-center">
  8. <div class="col-12 col-lg-6">
  9. <EditForm Model="@_loginUser" OnValidSubmit="() => OnLogin()">
  10. <DataAnnotationsValidator />
  11. <div class="input-group mb-3">
  12. <span class="input-group-text" style="width: 100px;">Username</span>
  13. <InputText class="form-control" @bind-Value="_loginUser.Username" disabled="@_authenticating" />
  14. <div class="text-danger">
  15. <ValidationMessage For="@(() => _loginUser.Username)" />
  16. </div>
  17. </div>
  18. <div class="input-group mb-3">
  19. <span class="input-group-text" style="width: 100px;">Password</span>
  20. <InputText class="form-control" type="password" @bind-Value="_loginUser.Password" disabled="@_authenticating" />
  21. <div class="text-danger">
  22. <ValidationMessage For="@(() => _loginUser.Password)" />
  23. </div>
  24. </div>
  25. <button type="submit" class="btn btn-primary w-100" disabled="@_authenticating">
  26. <text>Login</text>
  27. </button>
  28. @if (_loginFailed)
  29. {
  30. <div class="alert alert-danger mt-3" role="alert">
  31. <strong>Invalid username or password</strong>
  32. </div>
  33. }
  34. </EditForm>
  35. </div>
  36. </div>
  37. </div>
  38. @code {
  39. private LoginUserModel _loginUser = new();
  40. private bool _authenticating = false;
  41. private bool _loginFailed = false;
  42. protected override async Task OnInitializedAsync()
  43. {
  44. AuthenticationState authState = await AuthState.GetAuthenticationStateAsync();
  45. ClaimsPrincipal user = authState.User;
  46. if (user is not null
  47. && user.Identity is not null
  48. && user.Identity.IsAuthenticated)
  49. {
  50. Nav.NavigateTo("");
  51. }
  52. }
  53. private void OnLogin()
  54. {
  55. _loginFailed = false;
  56. // Authenticate user and update application state
  57. bool result = Auth.Login(_loginUser);
  58. if(!result)
  59. {
  60. _loginFailed = true;
  61. }
  62. }
  63. }

AuthenticationService.cs:

  1. using BlazorSimpleAuth.Models;
  2. using Microsoft.AspNetCore.Components.Authorization;
  3. namespace BlazorSimpleAuth.Authentication;
  4. public class AuthenticationService : IAuthenticationService
  5. {
  6. private readonly AuthenticationStateProvider _authStateProvider;
  7. public AuthenticationService(AuthenticationStateProvider authStateProvider)
  8. {
  9. _authStateProvider = authStateProvider;
  10. }
  11. public bool Login(LoginUserModel loginUser)
  12. {
  13. ArgumentNullException.ThrowIfNull(loginUser);
  14. ArgumentNullException.ThrowIfNull(loginUser.Username);
  15. ArgumentNullException.ThrowIfNull(loginUser.Password);
  16. // This code here would never fly in production, and is for demo purposes only. This is
  17. // the spot you would farm out your authentication to a proper identity provider.
  18. if (loginUser.Username.Equals("admin", StringComparison.InvariantCultureIgnoreCase)
  19. && loginUser.Password.Equals("password", StringComparison.InvariantCultureIgnoreCase))
  20. {
  21. ((SimpleAuthStateProvider)_authStateProvider).NotifyLoginUser(loginUser);
  22. return true;
  23. }
  24. return false;
  25. }
  26. public void Logout()
  27. {
  28. ((SimpleAuthStateProvider)_authStateProvider).NotifyUserLogout();
  29. }
  30. }

SimpleAuthStateProvider.cs:

  1. using BlazorSimpleAuth.Models;
  2. using Microsoft.AspNetCore.Components.Authorization;
  3. using System.Security.Claims;
  4. namespace BlazorSimpleAuth.Authentication;
  5. public sealed class SimpleAuthStateProvider : AuthenticationStateProvider
  6. {
  7. private readonly AuthenticationState _anonymous;
  8. private ClaimsIdentity _identity = new();
  9. public SimpleAuthStateProvider()
  10. {
  11. _anonymous = new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
  12. }
  13. public override Task<AuthenticationState> GetAuthenticationStateAsync()
  14. {
  15. ClaimsPrincipal user = new(_identity);
  16. return Task.FromResult(new AuthenticationState(user));
  17. }
  18. public void NotifyLoginUser(LoginUserModel loginUser)
  19. {
  20. ArgumentNullException.ThrowIfNull(loginUser);
  21. ArgumentNullException.ThrowIfNull(loginUser.Username);
  22. ArgumentNullException.ThrowIfNull(loginUser.Password);
  23. _identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, loginUser.Username) }, "SimpleDemo");
  24. ClaimsPrincipal user = new(_identity);
  25. NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(user)));
  26. }
  27. public void NotifyUserLogout()
  28. {
  29. _identity = new ClaimsIdentity();
  30. NotifyAuthenticationStateChanged(Task.FromResult(_anonymous));
  31. }
  32. }

此外,如果您想查看Blazor Dating应用程序的示例实现,用于演示/教育/非现实世界的目的,您可以查看此存储库:https://github.com/CodeFontana/DatingApp
然而,这使用Blazor WebAssembly作为前端/客户端,并由Web API支持,该API使用EF Core管理所有数据,包括应用内用户身份管理。
无论如何,希望这能帮助你找到正确的方向。

展开查看全部

相关问题