ASP.NET
对应的官方页面地址
入门
使用我们的 NuGet 包将简化与 ASP.NET Identity 的集成过程,带来更顺畅、更高效的集成体验。
dotnet add package Passwordless.AspNetCore
引导现在是一个简单的过程,其中将 Passwordless 添加到 IdentityBuilder
成为必要步骤。
下面的示例假设您的 appsettings.json
将在关键 Passwordless
下添加所有配置设置。
builder.Services
.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<PasswordlessContext>()
.AddPasswordless(builder.Configuration.GetSection("Passwordless"));
您至少需要提供 ApiKey
(公钥)和 ApiSecret
(私钥)。
{
"Passwordless": {
"ApiKey": "***:public:***",
"ApiSecret": "***:secret:***",
"Register": {
"Discoverable": true
}
}
}
现在,我们需要修改 WebApplication
对象以添加 Passwordless 路由,以便更轻松地注册、登录和管理凭据。
端点记录在本页后面的部分中。
app.MapPasswordless(enableRegisterEndpoint: true);
现在我们将在 /Account/Register
创建注册页面。当我们加载页面时,我们将向用户呈现一个表单。
当我们单击 Register
按钮时,将调用 OnPostAsync
。当表单有效时,我们将设置标志,该标志将允许我们的 Javascript 代码运行以允许注册令牌。
调用 POST /passwordless-register
将创建我们的 IdentityUser
并在其响应中返回注册令牌。然后我们将能够使用该令牌来创建我们的通行密钥。
@page
@using Passwordless.Net
@using Microsoft.Extensions.Options
@using Passwordless.AspNetCore
@model RegisterModel
@inject IOptions<PasswordlessAspNetCoreOptions> PasswordlessOptions;
@{
ViewData["Title"] = "Register";
}
<h1>@ViewData["Title"]</h1>
@{
var canAddPasskeys = ViewData["CanAddPasskeys"] is true;
}
<div class="row">
<div class="col-12">
<form class="needs-validation" action="" method="POST">
<div class="mb-3">
<label asp-for="Form.Username" class="form-label">Username</label>
<input
placeholder="Jane Doe"
type="text"
asp-for="Form.Username"
class="form-control"
id="username"/>
<span class="text-danger" asp-validation-for="Form.Username"></span>
</div>
<div class="mb-3">
<label asp-for="Form.Email" class="form-label">Email</label>
<input
placeholder="janedoe@example.org"
type="text"
asp-for="Form.Email"
class="form-control"
id="email"/>
<span class="text-danger" asp-validation-for="Form.Email"></span>
</div>
<div class="text-danger" asp-validation-summary="ModelOnly"></div>
<div>
<button type="submit" class="btn-primary">Register</button>
</div>
</form>
</div>
</div>
@if (canAddPasskeys)
{
<script src="https://cdn.passwordless.dev/dist/1.1.0/umd/passwordless.umd.js"></script>
<script>
async function register() {
const username = document.getElementById('username').value;
const email = document.getElementById('email').value;
const registrationRequest = {
email: email,
username: username,
displayName: username,
aliases: [email]
};
const registrationResponse = await fetch('/passwordless-register', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(registrationRequest)
});
// 如果没有错误,则进行反序列化,然后使用返回的令牌创建我们的通行密钥
if (registrationResponse.ok) {
const registrationResponseJson = await registrationResponse.json();
const token = registrationResponseJson.token;
// 我们需要使用从 https://cdn.passwordless.dev/dist/1.1.0/umd/passwordless.umd.js 导入的客户端。
const p = new Passwordless.Client({
apiKey: '@PasswordlessOptions.Value.ApiKey',
apiUrl: '@PasswordlessOptions.Value.ApiUrl'
});
const registeredPasskeyResponse = await p.register(token, email);
}
}
register();
</script>
}
public IActionResult OnGet()
{
if (HttpContext.User.Identity is { IsAuthenticated: true })
{
return LocalRedirect("/");
}
return Page();
}
public async Task OnPostAsync(FormModel form, CancellationToken cancellationToken)
{
if (!ModelState.IsValid) return;
_logger.LogInformation("Registering user {username}", form.Username);
ViewData["CanAddPasskeys"] = true;
}
public FormModel Form { get; init; } = new();
关于登录页面 /Account/Login
,单击「Login」按钮将再次触发一个类似的标志设置,从而执行我们的 JavaScript 代码的执行。
您可以采取两种方法。您可以请求一个「alias」来验证哪些通行密钥与别名对应,或者如果您有可发现的凭据,可能就不需要输入表单了。
登录过程与注册过程不同。在登录过程中,您将向身份验证器请求有效的通行密钥,以获取一个身份验证令牌。随后,该身份验证令牌将被传输到您的后端以启动会话。
使用「Passwordless ASP.NET Identity SDK」,您可以通过简单调用 POST /passwordless-login 来简化此过程,并且 SDK 将为您处理所有必要的步骤。
身份验证成功后,我们的示例应用程序将自动将您重定向到 /Authorized/HelloWorld 页面,该页面需要您登录才能访问。
@page
@model LoginModel
@using Microsoft.Extensions.Options
@using Passwordless.AspNetCore
@inject IOptions<PasswordlessAspNetCoreOptions> PasswordlessOptions;
@{
ViewData["Title"] = "Login";
}
<h1>@ViewData["Title"]</h1>
@{
var canLogin = ViewData["CanLogin"] != null && (bool)ViewData["CanLogin"];
}
<div class="row">
<div class="col-12">
<form class="needs-validation" action="" method="POST">
<div class="mb-3">
<label asp-for="Form.Email" class="form-label">Email</label>
<input
placeholder="janedoe@example.org"
type="text"
asp-for="Form.Email"
class="form-control"
id="email"/>
<span class="text-danger" asp-validation-for="Form.Email"></span>
</div>
<div class="text-danger" asp-validation-summary="ModelOnly"></div>
<div>
<button type="submit" class="btn-primary">Login</button>
</div>
</form>
</div>
</div>
@if (canLogin)
{
<script src="https://cdn.passwordless.dev/dist/1.1.0/umd/passwordless.umd.js"></script>
<script>
async function login() {
const alias = document.getElementById('email').value;
const p = new Passwordless.Client({
apiKey: '@PasswordlessOptions.Value.ApiKey',
apiUrl: '@PasswordlessOptions.Value.ApiUrl'
});
const loginPasskeyResponse = await p.signinWithAlias(alias);
if (!loginPasskeyResponse) {
return;
}
const loginRequest = {
token: loginPasskeyResponse.token
};
const loginResponse = await fetch('/passwordless-login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(loginRequest)
});
if (loginResponse.ok) {
console.log('login successful: ' + (await loginResponse.text()));
// Redirect to authorized page /Authorized/HelloWorld
window.location.href = '/Authorized/HelloWorld';
}
}
login();
</script>
}
如果我们在已通过身份验证的情况下访问登录页面,我们希望重定向到其他地方。
public IActionResult OnGet()
{
if (HttpContext.User.Identity is { IsAuthenticated: true })
{
return LocalRedirect("/");
}
return Page();
}
public async Task OnPostAsync(LoginForm form, CancellationToken cancellationToken)
{
if (!ModelState.IsValid) return;
_logger.LogInformation("Logging in user {email}", form.Email);
ViewData["CanLogin"] = true;
}
public LoginForm Form { get; } = new();
然后,您可以从 HttpContext
访问有关登录用户的信息:
public class HelloWorldModel : PageModel
{
private readonly ILogger<HelloWorldModel> _logger;
public HelloWorldModel(ILogger<HelloWorldModel> logger)
{
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public void OnGet()
{
var identity = HttpContext.User.Identity ;
var email = User.FindFirstValue(ClaimTypes.Email);
AuthenticatedUser = new AuthenticatedUserModel(identity.Name, email);
}
public AuthenticatedUserModel AuthenticatedUser { get; private set; }
}
public record AuthenticatedUserModel(string Username, string Email);
配置
高级
如果您需要更大的灵活性,我们邀请您探索我们的 JavaScript 客户端库和 .NET SDK。如果您希望对 ASP.NET Identity 框架进行更精细的控制,或者希望进行完全自定义的实施,则此选项特别合适。
最后更新于