您的问题有 2 种解决方案。选择你喜欢的任何一个。
解决方案 1:
您使用 LDAP 对用户进行身份验证,但使用身份来存储角色、声明等并以这种方式授权用户。
如果是这种情况,您可以简单地覆盖 CheckPasswordAsync 方法来检查某些 LDAP 服务器(例如 Active Directory)的密码。
看看这个答案,它确实是这样做的:
https://stackoverflow.com/a/74734478/8644294
解决方案 2:
您可以使用 LDAP 在没有身份数据库的情况下对用户进行身份验证和授权。在这种情况下,您正在查看 Cookie 身份验证。
为此,启动一个新的应用程序,不要选择任何身份验证。并遵循本指南:
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/cookie?view=aspnetcore-7.0
您不需要添加任何控制器。只需为例如创建一个 Razor 页面:登录.cshtml.
例如:
@page
@model LoginModel
@{
ViewData["Title"] = "Log in";
}
<h1>@ViewData["Title"]</h1>
<div class="row">
<div class="col-md-4">
<section>
<form id="account" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-floating">
<input asp-for="Input.Username" class="form-control" autocomplete="username" aria-required="true" />
<label asp-for="Input.Username" class="form-label"></label>
<span asp-validation-for="Input.Username" class="text-danger"></span>
</div>
<div class="form-floating">
<input asp-for="Input.Password" class="form-control" autocomplete="current-password" aria-required="true" />
<label asp-for="Input.Password" class="form-label"></label>
<span asp-validation-for="Input.Password" class="text-danger"></span>
</div>
<div>
<button id="login-submit" type="submit" class="w-100 btn btn-lg btn-primary">Log in</button>
</div>
</form>
</section>
</div>
</div>
并在后面的代码中实现登录:
using System.Security.Claims;
using Microsoft.AspNetCore.Authentication.Cookies;
using System.DirectoryServices.AccountManagement;
public class LoginModel : PageModel
{
private readonly ILogger<LoginModel> _logger;
public LoginModel(ILogger<LoginModel> logger)
{
_logger = logger;
}
[BindProperty]
public InputModel Input { get; set; }
public string ReturnUrl { get; set; }
[TempData]
public string ErrorMessage { get; set; }
public class InputModel
{
[Required]
[Display(Name = "User name")]
public string Username { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
public async Task OnGetAsync(string returnUrl = null)
{
if (!string.IsNullOrEmpty(ErrorMessage))
{
ModelState.AddModelError(string.Empty, ErrorMessage);
}
returnUrl ??= Url.Content("~/");
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
ReturnUrl = returnUrl;
}
public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
returnUrl ??= Url.Content("~/");
if (ModelState.IsValid)
{
// Write your logic on how to sign in using LDAP here.
// For an example, I'm using Active Direcotry as LDAP server here.
using PrincipalContext principalContext = new(ContextType.Domain);
bool adSignOnResult = principalContext.ValidateCredentials(Input.Username.ToUpper(), Input.Password);
if (!adSignOnResult)
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return Page();
}
// If LDAP login is successful:
var roles = // Write logic to grab roles of this user from LDAP server such as Active directory
var claims = new List<Claim>();
foreach (var role in roles)
{
var claim = new claim(claimtypes.role, role);
claims.add(claim);
}
// Populate other claims
claims.Add(new Claim(ClaimTypes.Name, username));
// Create claims idenity:
var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
// Create claims principal
var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
// Now signin this claimsPrincipal:
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal,
new AuthenticationProperties());
_logger.LogInformation("User logged in.");
return LocalRedirect(returnUrl);
}
// If we got this far, something failed, redisplay form
return Page();
}
}
但是当我想使用其他用户数据源时它会是什么样子
存储(在我的示例 LDAP 中)?
就个人而言,我自己还没有这样做,但是您应该能够使用自己的自定义逻辑更新该类,访问 LDAP 服务器并检查一些规则以确保用户应该登录。有关此类的更多信息,@987654323 @.
你不必使用那个类。如果您担心较长的身份验证会话,您可以将 cookie 身份验证间隔设置为一个较小的时间段。
比如设置在Program.cs:
services.ConfigureApplicationCookie(ops =>
ops.ExpireTimeSpan = TimeSpan.FromMinutes(10); <---- This guy
ops.SlidingExpiration = true;
});