跳转到主要内容

标签(标签)

资源精选(342) Go开发(108) Go语言(103) Go(99) angular(82) LLM(75) 大语言模型(63) 人工智能(53) 前端开发(50) LangChain(43) golang(43) 机器学习(39) Go工程师(38) Go程序员(38) Go开发者(36) React(33) Go基础(29) Python(24) Vue(22) Web开发(20) Web技术(19) 精选资源(19) 深度学习(19) Java(18) ChatGTP(17) Cookie(16) android(16) 前端框架(13) JavaScript(13) Next.js(12) 安卓(11) typescript(10) 资料精选(10) NLP(10) 第三方Cookie(9) Redwoodjs(9) LLMOps(9) Go语言中级开发(9) 自然语言处理(9) 聊天机器人(9) PostgreSQL(9) 区块链(9) mlops(9) 安全(9) 全栈开发(8) ChatGPT(8) OpenAI(8) Linux(8) AI(8) GraphQL(8) iOS(8) 软件架构(7) Go语言高级开发(7) AWS(7) C++(7) 数据科学(7) whisper(6) Prisma(6) 隐私保护(6) RAG(6) JSON(6) DevOps(6) 数据可视化(6) wasm(6) 计算机视觉(6) 算法(6) Rust(6) 微服务(6) 隐私沙盒(5) FedCM(5) 语音识别(5) Angular开发(5) 快速应用开发(5) 提示工程(5) Agent(5) LLaMA(5) 低代码开发(5) Go测试(5) gorm(5) REST API(5) 推荐系统(5) WebAssembly(5) GameDev(5) CMS(5) CSS(5) machine-learning(5) 机器人(5) 游戏开发(5) Blockchain(5) Web安全(5) Kotlin(5) 低代码平台(5) 机器学习资源(5) Go资源(5) Nodejs(5) PHP(5) Swift(5) 智能体(4) devin(4) Blitz(4) javascript框架(4) Redwood(4) GDPR(4) 生成式人工智能(4) Angular16(4) Alpaca(4) SAML(4) JWT(4) JSON处理(4) Go并发(4) kafka(4) 移动开发(4) 移动应用(4) security(4) 隐私(4) spring-boot(4) 物联网(4) nextjs(4) 网络安全(4) API(4) Ruby(4) 信息安全(4) flutter(4) 专家智能体(3) Chrome(3) CHIPS(3) 3PC(3) SSE(3) 人工智能软件工程师(3) LLM Agent(3) Remix(3) Ubuntu(3) GPT4All(3) 软件开发(3) 问答系统(3) 开发工具(3) 最佳实践(3) RxJS(3) SSR(3) Node.js(3) Dolly(3) 移动应用开发(3) 编程语言(3) 低代码(3) IAM(3) Web框架(3) CORS(3) 基准测试(3) Go语言数据库开发(3) Oauth2(3) 并发(3) 主题(3) Theme(3) earth(3) nginx(3) 软件工程(3) azure(3) keycloak(3) 生产力工具(3) gpt3(3) 工作流(3) C(3) jupyter(3) 认证(3) prometheus(3) GAN(3) Spring(3) 逆向工程(3) 应用安全(3) Docker(3) Django(3) R(3) .NET(3) 大数据(3) Hacking(3) 渗透测试(3) C++资源(3) Mac(3) 微信小程序(3) Python资源(3) JHipster(3) 大型语言模型(2) 语言模型(2) 可穿戴设备(2) JDK(2) SQL(2) Apache(2) Hashicorp Vault(2) Spring Cloud Vault(2) Go语言Web开发(2) Go测试工程师(2) WebSocket(2) 容器化(2) AES(2) 加密(2) 输入验证(2) ORM(2) Fiber(2) Postgres(2) Gorilla Mux(2) Go数据库开发(2) 模块(2) 泛型(2) 指针(2) HTTP(2) PostgreSQL开发(2) Vault(2) K8s(2) Spring boot(2) R语言(2) 深度学习资源(2) 半监督学习(2) semi-supervised-learning(2) architecture(2) 普罗米修斯(2) 嵌入模型(2) productivity(2) 编码(2) Qt(2) 前端(2) Rust语言(2) NeRF(2) 神经辐射场(2) 元宇宙(2) CPP(2) 数据分析(2) spark(2) 流处理(2) Ionic(2) 人体姿势估计(2) human-pose-estimation(2) 视频处理(2) deep-learning(2) kotlin语言(2) kotlin开发(2) burp(2) Chatbot(2) npm(2) quantum(2) OCR(2) 游戏(2) game(2) 内容管理系统(2) MySQL(2) python-books(2) pentest(2) opengl(2) IDE(2) 漏洞赏金(2) Web(2) 知识图谱(2) PyTorch(2) 数据库(2) reverse-engineering(2) 数据工程(2) swift开发(2) rest(2) robotics(2) ios-animation(2) 知识蒸馏(2) 安卓开发(2) nestjs(2) solidity(2) 爬虫(2) 面试(2) 容器(2) C++精选(2) 人工智能资源(2) Machine Learning(2) 备忘单(2) 编程书籍(2) angular资源(2) 速查表(2) cheatsheets(2) SecOps(2) mlops资源(2) R资源(2) DDD(2) 架构设计模式(2) 量化(2) Hacking资源(2) 强化学习(2) flask(2) 设计(2) 性能(2) Sysadmin(2) 系统管理员(2) Java资源(2) 机器学习精选(2) android资源(2) android-UI(2) Mac资源(2) iOS资源(2) Vue资源(2) flutter资源(2) JavaScript精选(2) JavaScript资源(2) Rust开发(2) deeplearning(2) RAD(2)

category

安全上下文:此功能仅在安全上下文(HTTPS)、某些或所有支持的浏览器中可用。

Web身份验证API(WebAuthn)是凭证管理API的扩展,可通过公钥加密实现强身份验证,实现无密码身份验证和无SMS文本的安全多因素身份验证(MFA)。

注意:密钥是web身份验证的一个重要用例;有关实现的详细信息,请参阅为无密码登录创建密钥【 Create a passkey for passwordless logins】和通过表单自动填充使用密钥登录【 Sign in with a passkey through form autofill】。另请参阅Google Identity>Passwordless login with passkeys。

WebAuthn的概念和用法


WebAuthn使用非对称(公钥)加密技术代替密码或短信文本来注册、验证和对网站进行多因素验证。这有一些好处:

  • 防止网络钓鱼:创建虚假登录网站的攻击者无法以用户身份登录,因为签名会随着网站的来源而更改。
  • 减少了数据泄露的影响:开发人员不需要对公钥进行散列,如果攻击者能够访问用于验证身份验证的公钥,则无法进行身份验证,因为它需要私钥。
  • 易受密码攻击:一些用户可能会重复使用密码,攻击者可能会获取其他网站的用户密码(例如通过数据泄露)。此外,文本密码比数字签名更容易使用暴力。

许多网站已经拥有允许用户注册新帐户或登录现有帐户的页面,WebAuthn可以替代或增强系统的身份验证部分。它扩展了凭证管理API【 Credential Management API,】,抽象了用户代理和身份验证程序之间的通信,并提供了以下新功能:

  • 当navigator.credentials.create()与publicKey选项一起使用时,用户代理会通过验证器创建新的凭据,用于注册新帐户或将新的非对称密钥对与现有帐户关联。
    • 注册新帐户时,这些凭据存储在服务器(也称为服务或依赖方)上,随后可用于用户登录。
    • 非对称密钥对存储在验证器中,然后该验证器可以用于例如在MFA期间向依赖方验证用户。验证器可以嵌入到用户代理、操作系统(如Windows Hello)中,也可以是物理令牌(如USB或蓝牙安全密钥)。
  • 当navigator.certificate.get()与publicKey选项一起使用时,用户代理使用一组现有的凭据向依赖方进行身份验证(作为主登录名,或在如上所述的MFA期间提供附加因素)。

在最基本的形式中,create()和get()都从服务器接收一个非常大的随机数,称为“challenge”,并将私钥签名的challenge返回给服务器。这向服务器证明,用户拥有身份验证所需的私钥,而不会在网络上泄露任何机密。

注意:“挑战”必须是一个大小至少为16字节的随机信息缓冲区。

创建密钥对并注册用户


为了说明凭据创建过程是如何工作的,让我们描述一下当用户想要向依赖方注册凭据时发生的典型流程:

  • 依赖方服务器使用适当的安全机制(例如Fetch或XMLHttpRequest)将用户和依赖方信息连同“质询”一起发送到处理注册过程的web应用程序。
    • 注意:依赖方服务器和网络应用程序之间共享信息的格式取决于应用程序。推荐的方法是将JSON类型的表示对象交换为凭据和凭据选项。在PublicKeyCredential中创建了方便的方法,用于将JSON表示转换为身份验证API所需的形式:parseCreationOptionsFromJSON()、parseRequestOptionsFromJSON()和PublicKeyCredential.toJSON()
  • web应用程序代表依赖方,通过navigator.credentials.create()调用,通过验证器启动新凭据的生成。此调用传递一个publicKey选项,指定设备功能,例如,设备是否提供自己的用户身份验证(例如,生物识别)。典型的create()调用可能如下所示:
JS

let credential = await navigator.credentials.create({
  publicKey: {
    challenge: new Uint8Array([117, 61, 252, 231, 191, 241, ...]),
    rp: { id: "acme.com", name: "ACME Corporation" },
    user: {
      id: new Uint8Array([79, 252, 83, 72, 214, 7, 89, 26]),
      name: "jamiedoe",
      displayName: "Jamie Doe"
    },
    pubKeyCredParams: [ {type: "public-key", alg: -7} ]
  }
});

 

create()调用的参数与经过签名的SHA-256哈希一起传递给验证器,以确保其不会被篡改。

  • 在验证器【authenticator】获得用户同意后,它生成一个密钥对,并将公钥和可选的签名证明返回给web应用程序。当create()调用返回的Promise以PublicKeyCredential对象实例的形式(PublicKeyCredential.response属性包含证明信息)实现时,会提供此选项。
  • web应用程序再次使用适当的机制将PublicKeyCredential转发到服务器。
  • 服务器存储公钥和用户标识,以记住凭据,以便将来进行身份验证。在此过程中,它会执行一系列检查,以确保注册完整且未被篡改。其中包括:
    • 验证质询是否与发送的质询相同。
    • 确保原产地是预期的原产地。
    • 验证签名和证明是否使用了最初用于生成密钥par的验证器的特定模型的正确证书链。

警告:认证为依赖方提供了一种确定验证器来源的方法。依赖方不应试图维护身份验证程序的允许列表。

对用户进行身份验证


在用户向WebAuthn注册后,他们可以使用该服务进行身份验证(即登录)。身份验证流程与注册流程类似,主要区别在于身份验证:

  • 不需要用户或依赖方信息
  • 使用先前为服务生成的密钥对而不是验证器的密钥对创建断言。

典型的身份验证流程如下:

  • 依赖方生成一个“质询”,并使用适当的安全机制将其与依赖方和用户凭据的列表一起发送给用户代理。它还可以指示在哪里查找凭据,例如,在本地内置验证器上,或通过USB、BLE等在外部验证器上。
  • 浏览器要求验证器通过navigator.certificate.get()调用对质询进行签名,该调用在publicKey选项中传递凭据。典型的get()调用可能如下所示:

JS

let credential = await navigator.credentials.get({
  publicKey: {
    challenge: new Uint8Array([139, 66, 181, 87, 7, 203, ...]),
    rpId: "acme.com",
    allowCredentials: [{
      type: "public-key",
      id: new Uint8Array([64, 66, 25, 78, 168, 226, 174, ...])
    }],
    userVerification: "required",
  }
});

 


get()调用的参数被传递给验证器以处理身份验证。

  • 如果验证器包含给定的凭据之一,并且能够成功签署质询,则在收到用户同意后,它会向web应用程序返回一个已签名的断言。当get()调用返回的Promise以PublicKeyCredential对象实例的形式(PublicKeyCredential.response属性包含断言信息)实现时,会提供此选项。
  • web应用程序将签名的断言转发到依赖方服务器,供依赖方验证。验证检查包括:
    • 使用在注册请求期间存储的公钥来验证验证器的签名。
    • 确保验证器签名的质询与服务器生成的质询匹配。
    • 正在检查依赖方ID是否为此服务所需的ID。
  • 一旦由服务器验证,则认为身份验证流是成功的。

控制对API的访问


WebAuthn的可用性可以使用权限策略来控制,该策略特别指定了两个指令:

  • publickey-credentials-create:使用publickey选项控制navigator.credentials.create()的可用性。
  • publickey-credentials-get:使用publickey选项控制navigator.credentials.get()的可用性。

这两个指令都有一个默认的allowlist值“self”,这意味着默认情况下,这些方法可以在顶级文档上下文中使用。此外,get()可以用于从与最顶端文档相同的来源加载的嵌套浏览上下文。get()和create()可以用于从不同来源加载到最顶端文档的嵌套浏览上下文(即在跨来源<iframes>中),如果公钥凭据分别允许get和公钥凭据create Permission Policy指令。对于跨原点create()调用,其中权限是由iframe上的allow=授予的,帧也必须具有瞬态激活。

注意:当策略禁止使用这些方法时,它们返回的promise将被NotAllowedError DOMException拒绝。

基本访问控制


如果您希望只允许访问特定的子域,您可以这样提供:

HTTP

Permissions-Policy: publickey-credentials-get=("https://subdomain.example.com")
Permissions-Policy: publickey-credentials-create=("https://subdomain.example.com")


允许在<iframe>中嵌入create和get()调用


如果您希望在<iframe>中使用get()或create()进行身份验证,需要遵循以下几个步骤:

  • 嵌入依赖方网站的网站必须通过允许属性提供权限:
    • 如果使用get():

HTML

<iframe
  src="https://auth.provider.com"
  allow="publickey-credentials-get *">
</iframe>

 

  • 如果使用create():

HTML
 

<iframe
  src="https://auth.provider.com"
  allow="publickey-credentials-create 'self' https://a.auth.provider.com https://b.auth.provider.com">
</iframe>


如果create()被称为交叉原点,则<iframe>也必须具有瞬态激活。

  • 依赖方网站必须通过“权限策略”标头为上述访问提供权限:

HTTP

Permissions-Policy: publickey-credentials-get=*
Permissions-Policy: publickey-credentials-create=*


或者只允许特定的URL将依赖方网站嵌入<iframe>中:
HTTP

Permissions-Policy: publickey-credentials-get=("https://subdomain.example.com")
Permissions-Policy: publickey-credentials-create=("https://*.auth.provider.com")


接口


AuthenticatorAssertionResponse


向服务提供证据,证明验证器具有成功处理CredentialsContainer.get()调用发起的身份验证请求所需的密钥对。在get()Promise实现时获得的PublicKeyCredential实例的响应属性中可用。

AuthenticatorAttestationResponse


WebAuthn凭据注册的结果(即CredentialsContainer.create()调用)。它包含有关服务器执行WebAuthn断言所需的凭据的信息,例如其凭据ID和公钥。在create()Promise实现时获得的PublicKeyCredential实例的响应属性中可用。

AuthenticatorResponse


AuthenticatorAttestationResponse和AuthenticatorAssertionResponse的基本接口。

PublicKeyCredential


提供有关公钥/私钥对的信息,该对是使用不可钓鱼和防数据泄露的非对称密钥对而不是密码登录服务的凭据。当通过create()或get()调用返回的Promise实现时获得。

对其他接口的扩展


CredentialsContainer.create(), the publicKey option
如上所述,使用publicKey选项调用create()将通过验证器启动新的非对称密钥凭据的创建。

CredentialsContainer.get(), the publicKey option
使用publicKey选项调用get()指示用户代理使用现有的一组凭据向依赖方进行身份验证。

示例


演示站点


用法示例


注意:出于安全原因,如果浏览器窗口在调用挂起时失去焦点,则会取消Web验证API调用(create()和get())。

JS

// sample arguments for registration
const createCredentialDefaultArgs = {
  publicKey: {
    // Relying Party (a.k.a. - Service):
    rp: {
      name: "Acme",
    },
    // User:
    user: {
      id: new Uint8Array(16),
      name: "carina.p.anand@example.com",
      displayName: "Carina P. Anand",
    },
    pubKeyCredParams: [
      {
        type: "public-key",
        alg: -7,
      },
    ],
    attestation: "direct",
    timeout: 60000,
    challenge: new Uint8Array([
      // must be a cryptographically random number sent from a server
      0x8c, 0x0a, 0x26, 0xff, 0x22, 0x91, 0xc1, 0xe9, 0xb9, 0x4e, 0x2e, 0x17,
      0x1a, 0x98, 0x6a, 0x73, 0x71, 0x9d, 0x43, 0x48, 0xd5, 0xa7, 0x6a, 0x15,
      0x7e, 0x38, 0x94, 0x52, 0x77, 0x97, 0x0f, 0xef,
    ]).buffer,
  },
};

// sample arguments for login
const getCredentialDefaultArgs = {
  publicKey: {
    timeout: 60000,
    // allowCredentials: [newCredential] // see below
    challenge: new Uint8Array([
      // must be a cryptographically random number sent from a server
      0x79, 0x50, 0x68, 0x71, 0xda, 0xee, 0xee, 0xb9, 0x94, 0xc3, 0xc2, 0x15,
      0x67, 0x65, 0x26, 0x22, 0xe3, 0xf3, 0xab, 0x3b, 0x78, 0x2e, 0xd5, 0x6f,
      0x81, 0x26, 0xe2, 0xa6, 0x01, 0x7d, 0x74, 0x50,
    ]).buffer,
  },
};

// register / create a new credential
navigator.credentials
  .create(createCredentialDefaultArgs)
  .then((cred) => {
    console.log("NEW CREDENTIAL", cred);
    // normally the credential IDs available for an account would come from a server
    // but we can just copy them from above…
    const idList = [
      {
        id: cred.rawId,
        transports: ["usb", "nfc", "ble"],
        type: "public-key",
      },
    ];
    getCredentialDefaultArgs.publicKey.allowCredentials = idList;
    return navigator.credentials.get(getCredentialDefaultArgs);
  })
  .then((assertion) => {
    console.log("ASSERTION", assertion);
  })
  .catch((err) => {
    console.log("ERROR", err);
  });

 

规格

Web Authentication: An API for accessing Public Key Credentials - Level 3
# iface-pkcredential