Web Authn(2.75/3)

解决弃用问题
前端改进
This commit is contained in:
Chenx221 2024-03-17 17:24:26 +08:00
parent 413d60f3f4
commit 711c0cd31a
Signed by: chenx221
GPG Key ID: D7A9EC07024C3021
4 changed files with 42 additions and 19 deletions

View File

@ -16,6 +16,8 @@ use Webauthn\AuthenticatorAssertionResponse;
use Webauthn\AuthenticatorAssertionResponseValidator; use Webauthn\AuthenticatorAssertionResponseValidator;
use Webauthn\AuthenticatorAttestationResponse; use Webauthn\AuthenticatorAttestationResponse;
use Webauthn\AuthenticatorAttestationResponseValidator; use Webauthn\AuthenticatorAttestationResponseValidator;
use Webauthn\CeremonyStep\CeremonyStepManager;
use Webauthn\CeremonyStep\CeremonyStepManagerFactory;
use Webauthn\Denormalizer\WebauthnSerializerFactory; use Webauthn\Denormalizer\WebauthnSerializerFactory;
use Webauthn\Exception\AuthenticatorResponseVerificationException; use Webauthn\Exception\AuthenticatorResponseVerificationException;
use Webauthn\PublicKeyCredential; use Webauthn\PublicKeyCredential;
@ -596,7 +598,7 @@ class UserController extends Controller
{ {
if (Yii::$app->request->isPjax) { if (Yii::$app->request->isPjax) {
$publicKeyCredentialSourceRepository = $this->findCredentialModel($id); $publicKeyCredentialSourceRepository = $this->findCredentialModel($id);
if($publicKeyCredentialSourceRepository->user_id !== Yii::$app->user->id){ if ($publicKeyCredentialSourceRepository->user_id !== Yii::$app->user->id) {
Yii::$app->session->setFlash('error', '非法操作'); Yii::$app->session->setFlash('error', '非法操作');
return $this->redirect('info'); return $this->redirect('info');
} }
@ -612,6 +614,11 @@ class UserController extends Controller
} }
} }
/*
* 以下WebAuthn(FIFO)验证代码已经调好了,不要乱动
*/
/** /**
* 创建公钥凭证选项 * 创建公钥凭证选项
* @return Response * @return Response
@ -655,6 +662,8 @@ class UserController extends Controller
public function actionCreateCredential(): Response public function actionCreateCredential(): Response
{ {
$data = Yii::$app->request->getRawBody(); $data = Yii::$app->request->getRawBody();
$json_decode = json_decode($data, true);
$fido_name = empty($json_decode['fido_name']) ? '未命名的设备' : $json_decode['fido_name'];
$attestationStatementSupportManager = AttestationStatementSupportManager::create(); $attestationStatementSupportManager = AttestationStatementSupportManager::create();
$attestationStatementSupportManager->add(NoneAttestationStatementSupport::create()); $attestationStatementSupportManager->add(NoneAttestationStatementSupport::create());
$webauthnSerializerFactory = new WebauthnSerializerFactory($attestationStatementSupportManager); $webauthnSerializerFactory = new WebauthnSerializerFactory($attestationStatementSupportManager);
@ -665,14 +674,16 @@ class UserController extends Controller
return $this->asJson(['message' => 'Invalid response type']); return $this->asJson(['message' => 'Invalid response type']);
} }
// PHP Deprecated: // 什么时候更新开发文档?
// Since web-auth/webauthn-lib 4.8.0: $ceremonyStepManagerFactory = new CeremonyStepManagerFactory();
// The parameter "$attestationStatementSupportManager" is deprecated since 4.8.0 will be removed in 5.0.0. $ceremonyStepManager = $ceremonyStepManagerFactory->creationCeremony();
// Please set a CheckAttestationFormatIsKnownAndValid object into CeremonyStepManager object instead.
// in /vendor/symfony/deprecation-contracts/function.php on line 25
// MD, 这个问题在文档更新之前我是不会去解决的
$authenticatorAttestationResponseValidator = AuthenticatorAttestationResponseValidator::create( $authenticatorAttestationResponseValidator = AuthenticatorAttestationResponseValidator::create(
$attestationStatementSupportManager null,
null,
null,
null,
null,
$ceremonyStepManager
); );
$publicKeyCredentialCreationOptions = Yii::$app->session->get('publicKeyCredentialCreationOptions'); $publicKeyCredentialCreationOptions = Yii::$app->session->get('publicKeyCredentialCreationOptions');
@ -683,7 +694,7 @@ class UserController extends Controller
Yii::$app->params['domain'] Yii::$app->params['domain']
); );
$publicKeyCredentialSourceRepository = new PublicKeyCredentialSourceRepository(); $publicKeyCredentialSourceRepository = new PublicKeyCredentialSourceRepository();
$publicKeyCredentialSourceRepository->saveCredential($publicKeyCredentialSource, 'test'); //receive source $publicKeyCredentialSourceRepository->saveCredential($publicKeyCredentialSource, $fido_name); //receive source
return $this->asJson(['verified' => true]); return $this->asJson(['verified' => true]);
} catch (Throwable $e) { } catch (Throwable $e) {
return $this->asJson(['message' => $e->getMessage(), 'verified' => false]); return $this->asJson(['message' => $e->getMessage(), 'verified' => false]);
@ -753,7 +764,16 @@ class UserController extends Controller
} }
$PKCS = $webauthnSerializerFactory->create()->deserialize($publicKeyCredentialSourceRepository1->data, PublicKeyCredentialSource::class, 'json'); $PKCS = $webauthnSerializerFactory->create()->deserialize($publicKeyCredentialSourceRepository1->data, PublicKeyCredentialSource::class, 'json');
$authenticatorAssertionResponseValidator = AuthenticatorAssertionResponseValidator::create(); $ceremonyStepManagerFactory = new CeremonyStepManagerFactory();
$ceremonyStepManager = $ceremonyStepManagerFactory->requestCeremony();
$authenticatorAssertionResponseValidator = AuthenticatorAssertionResponseValidator::create(
null,
null,
null,
null,
null,
$ceremonyStepManager
);
$publicKeyCredentialRequestOptions = Yii::$app->session->get('publicKeyCredentialRequestOptions'); $publicKeyCredentialRequestOptions = Yii::$app->session->get('publicKeyCredentialRequestOptions');
try { try {
$publicKeyCredentialSource = $authenticatorAssertionResponseValidator->check( $publicKeyCredentialSource = $authenticatorAssertionResponseValidator->check(
@ -769,7 +789,7 @@ class UserController extends Controller
// Optional, but highly recommended, you can save the credential source as it may be modified // Optional, but highly recommended, you can save the credential source as it may be modified
// during the verification process (counter may be higher). // during the verification process (counter may be higher).
$publicKeyCredentialSourceRepository1->saveCredential($publicKeyCredentialSource, 'test'); $publicKeyCredentialSourceRepository1->saveCredential($publicKeyCredentialSource, '',false);
return $this->asJson(['verified' => true]); return $this->asJson(['verified' => true]);
} }

View File

@ -92,16 +92,19 @@ class PublicKeyCredentialSourceRepository extends ActiveRecord
* 保存PublicKeyCredentialSource对象到数据库 * 保存PublicKeyCredentialSource对象到数据库
* @param PublicKeyCredentialSource $PKCS * @param PublicKeyCredentialSource $PKCS
* @param string $name * @param string $name
* @param bool $isNewRecord
* @return bool * @return bool
* @throws JsonException * @throws JsonException
*/ */
public function saveCredential(PublicKeyCredentialSource $PKCS,string $name): bool public function saveCredential(PublicKeyCredentialSource $PKCS, string $name, bool $isNewRecord = true): bool
{ {
$jsonSerialize = $PKCS->jsonSerialize(); $jsonSerialize = $PKCS->jsonSerialize();
$this->public_key_credential_id = $jsonSerialize['publicKeyCredentialId']; $this->public_key_credential_id = $jsonSerialize['publicKeyCredentialId'];
$publicKeyCredentialSourceJson = json_encode($jsonSerialize, JSON_THROW_ON_ERROR); $publicKeyCredentialSourceJson = json_encode($jsonSerialize, JSON_THROW_ON_ERROR);
$this->data = $publicKeyCredentialSourceJson; $this->data = $publicKeyCredentialSourceJson;
$this->name = $name; if($isNewRecord){
$this->name = $name;
}
$this->user_id = Yii::$app->user->id; $this->user_id = Yii::$app->user->id;
return $this->save(); return $this->save();
} }

View File

@ -276,10 +276,11 @@ $darkMode = Yii::$app->user->identity->dark_mode;
<i class="fa-solid fa-key"></i> <i class="fa-solid fa-key"></i>
Passwordless验证 (Webauthn) (BETA) Passwordless验证 (Webauthn) (BETA)
</h5> </h5>
<div> <div class="input-group" id="totp_area" style="width: 50%">
<input type="text" class="form-control" placeholder="在这里为新的FIDO设备命名" aria-label="在这里为新的FIDO设备命名" name="fido_name" id="fido_name">
<?= Html::button('添加', ['id' => "webauthn_add", 'type' => 'button', 'class' => 'btn btn-primary btn-sm']) ?> <?= Html::button('添加', ['id' => "webauthn_add", 'type' => 'button', 'class' => 'btn btn-primary btn-sm']) ?>
<?= Html::button('测试', ['id' => "webauthn_verify", 'type' => 'button', 'class' => 'btn btn-primary btn-sm']) ?> <?= Html::button('测试', ['id' => "webauthn_verify", 'type' => 'button', 'class' => 'btn btn-primary btn-sm']) ?>
<?= Html::button('查看详情', ['id' => "webauthn_detail", 'type' => 'button', 'class' => 'btn btn-primary btn-sm']) ?> <?= Html::button('管理', ['id' => "webauthn_detail", 'type' => 'button', 'class' => 'btn btn-primary btn-sm']) ?>
</div> </div>
<div class="alert alert-success" role="alert" hidden> <div class="alert alert-success" role="alert" hidden>
<span id="webauthn_success"></span> <span id="webauthn_success"></span>
@ -422,7 +423,7 @@ Modal::end();
Modal::begin([ Modal::begin([
'title' => '<h4>管理已添加的Webauthn设备</h4>', 'title' => '<h4>管理已添加的Webauthn设备</h4>',
'id' => 'credentialModal', 'id' => 'credentialModal',
'size' => 'modal-lg', 'size' => 'modal-xl modal-fullscreen-xl-down',
]); ]);
echo Html::tag('div', '你可以在下方查看和删除已经添加的Webauthn设备', ['class' => 'modal-body']); echo Html::tag('div', '你可以在下方查看和删除已经添加的Webauthn设备', ['class' => 'modal-body']);

View File

@ -45,9 +45,8 @@ document.querySelector('.editable-username').addEventListener('click', function
}); });
document.querySelector('#webauthn_detail').addEventListener('click', function () { document.querySelector('#webauthn_detail').addEventListener('click', function () {
// $('#credentialModal').modal('show');
$.ajax({ $.ajax({
url: 'index.php?r=user%2Fcredential-list', // 替换为你的 API 路径 url: 'index.php?r=user%2Fcredential-list',
method: 'GET', method: 'GET',
success: function(data) { success: function(data) {
$('#pjax-container').html(data); $('#pjax-container').html(data);
@ -94,7 +93,7 @@ elemBegin.addEventListener('click', async () => {
throw error; throw error;
} }
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content'); const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
attResp.fido_name = document.getElementById('fido_name').value;
// POST the response to the endpoint that calls // POST the response to the endpoint that calls
const verificationResp = await fetch('index.php?r=user%2Fcreate-credential', { const verificationResp = await fetch('index.php?r=user%2Fcreate-credential', {
method: 'POST', method: 'POST',