Skaitmeninio ženklelio patikrinimas jūsų svetainėje (be iframe, be SDK)

Įdėkite į savo svetainę nedidelį JavaScript fragmentą (arba serverio pusės užklausą), kuris patikrina bet kurį Open Badge per viešą JSON-LD galinį tašką. Jokio iframe, jokių trečiųjų šalių sekliklių.

Nacho Coll Autorius Atnaujinta 9 min skaitymo
Įdėkite į savo svetainę nedidelį JavaScript fragmentą (arba serverio pusės užklausą), kuris patikrina bet kurį Open Badge per viešą JSON-LD galinį tašką. Jokio iframe, jokių trečiųjų šalių sekliklių.

Jei išduodate kvalifikacijos pažymėjimus, anksčiau ar vėliau kas nors paklaus: „Kaip žinoti, kad šis ženklelis tikras?“ Sąžiningas atsakymas niekada neturėtų būti „tikėkite PNG paveikslėliu“. Open Badge v2.0 šią problemą sprendžia viešu, mašininiu būdu skaitomu patikrinimo galiniu tašku, o „Patikrinta“ valdiklį savo svetainėje galite įdėti maždaug dešimčia kodo eilučių – be iframe, be trečiosios šalies įterpimo skripto ir be SDK.

Šiame įraše parodoma, kaip tiksliai iškviesti galinį tašką ir parodyti rezultatą – su gryna JavaScript bei serverio pusėje su Node ir Python. Taip pat aptariama, ką iš tikrųjų tikrina „patikrinimas“, kuo galinis taškas skiriasi nuo žmonėms skirtų puslapių, kuriuos badges.ninja jau suteikia gavėjams, ir klaidos, dėl kurių patikrinimo valdiklis atrodo baigtas, nors iš tikrųjų nieko neįrodo.

Ką iš tikrųjų reiškia „patikrinta“

Open Badge v2.0 patvirtinimas (assertion) yra JSON-LD dokumentas su fiksuota struktūra: pats patvirtinimas (kas jį gavo, kada), nuoroda į BadgeClass (kas tai yra, kas nustato kriterijus) ir nuoroda į išdavėjo profilį (kas už tai laiduoja). Kai „patikrinate“ ženklelį, iš tikrųjų tikrinate tris atskirus dalykus:

  1. Ar patvirtinimas egzistuoja ir pasiekiamas. Apdovanojimo ID yra tikras, o ne atspėtas ar suklastotas.
  2. Ar jis atšauktas. Išdavėjas gali atšaukti ženklelį vėliau – kai jis išduotas per klaidą, pažeista tvarka ar pasibaigė sertifikato galiojimas – o teisingas tikrintuvas privalo tai parodyti, o ne tik patvirtinti, kad įrašas egzistuoja.
  3. Ar grandinė laikosi kartu. Patvirtinimo nuorodos į ženklelį ir išdavėją iš tikrųjų nurodo realius, atitinkančius įrašus, o ne našlaitinius ar nesutampančius ID.

Patikrinimo valdiklis, kuris tik kreipiasi į URL ir tikrina 200 būseną, visiškai praleidžia 2 punktą. Atšauktas patvirtinimas vis tiek sėkmingai pasiekiamas – jis tiesiog turi atšaukimo žymą duomenyse. Jei valdiklis tikrina tik „ar užklausa pavyko“, atšauktas pažymėjimas bus rodomas kaip patikrintas, o tai blogiau nei visai neturėti valdiklio.

Viešas žmonėms skirtas puslapis ir API galinis taškas

Kiekvienas apdovanojimas, išduotas https://badges.ninja, gauna viešą URL, kuriuo gavėjai gali dalytis tiesiogiai, o jį peržiūrėti nereikia registruotis:

Public credential page

Būtent į šį puslapį dauguma gavėjų pateiks nuorodą iš LinkedIn, gyvenimo aprašymo ar el. laiško parašo – jis sukurtas žmonėms, rodo ženklelio paveikslėlį, išdavėją ir išdavimo datą, o jam veikti iš jūsų nieko nereikia. Žemiau aprašytas API galinis taškas grąžina tą patį patvirtinimą kaip struktūrizuotą JSON-LD – to jums ir reikia, kai kuriate savo sąsają, o ne tik nukreipiate į mūsiškę.

Galinis taškas

GET https://api.badges.ninja/certify-badge/award/{guid}

Autentifikavimo antraštė nereikalinga – tai sąmoningai viešas taškas, nes visa Open Badges esmė ta, kad bet kas (darbdavys, personalo specialistas, licencijavimo taryba) gali patikrinti pažymėjimą be paskyros. Visa sutarties informacija, įskaitant tikslius grąžinamo patvirtinimo laukų pavadinimus, pateikta patikrinimo dokumentacijoje.

Perduokite apdovanojimo GUID, kurį turėsite arba iš savo išdavimo įrašų, arba išskirsite iš badges.ninja/awards/<guid> nuorodos, kuria su jumis pasidalijo gavėjas.

Gryna JS: gauti ir parodyti

Tai ir yra visas valdiklis. Jokio kūrimo žingsnio, jokio npm paketo – tiesiog įdėkite į bet kurį puslapį:

<div id="badge-verify"></div>
<script>
  async function renderBadgeVerification(awardId, mountId) {
    const el = document.getElementById(mountId);
    el.textContent = "Checking badge status";
    try {
      const res = await fetch(
        `https://api.badges.ninja/certify-badge/award/${awardId}`
      );
      if (!res.ok) {
        el.textContent = "Credential not found.";
        return;
      }
      const assertion = await res.json();
      // —— revocation check first, a resolvable assertion isn't enough on its own
      if (assertion.revoked) {
        el.textContent = `Revoked: ${assertion.revocationReason || "no reason given"}`;
        return;
      }
      el.textContent = `Verified, issued ${new Date(assertion.issuedOn).toLocaleDateString()}`;
    } catch (err) {
      el.textContent = "Verification check failed.";
    }
  }
  renderBadgeVerification("REPLACE_WITH_AWARD_ID", "badge-verify");
</script>

Pakeiskite REPLACE_WITH_AWARD_ID tikru apdovanojimo GUID. Tai ir visa integracija kliento pusėje: nereikia kovoti su iframe riba dėl CSS ir nėra trečiosios šalies skripto, kuris kartu su patikrinimu įtrauktų savo analitiką ar sekimo pikselius.

Serverio pusė: Node

Jei verčiau tikrinti savo serveryje – pavyzdžiui, prieš rodydami „Patikrinto partnerio“ ženklelį jūsų valdomame profilio puslapyje arba prieš priimdami pažymėjimą kaip įrodymą registracijos eigoje – užklausa ta pati, tik be DOM dalies:

async function verifyAward(awardId) {
  const res = await fetch(
    `https://api.badges.ninja/certify-badge/award/${awardId}`
  );
  if (!res.ok) return { verified: false, reason: "not_found" };
  const assertion = await res.json();
  if (assertion.revoked) {
    return { verified: false, reason: assertion.revocationReason || "revoked" };
  }
  return { verified: true, issuedOn: assertion.issuedOn, badge: assertion.badge };
}

Serverio pusė: Python

import requests
# —— resolve the assertion, then check revocation before trusting it
def verify_award(award_id):
    res = requests.get(f"https://api.badges.ninja/certify-badge/award/{award_id}")
    if res.status_code != 200:
        return {"verified": False, "reason": "not_found"}
    assertion = res.json()
    if assertion.get("revoked"):
        return {"verified": False, "reason": assertion.get("revocationReason", "revoked")}
    return {"verified": True, "issued_on": assertion.get("issuedOn"), "badge": assertion.get("badge")}

Abu pavyzdžiai ne-200 atsakymą traktuoja kaip „nerasta“, o ne išmeta klaidą. Sugedęs ar atspėtas apdovanojimo ID viešam patikrinimo galiniam taškui yra įprasta įvestis, o ne išimtinė situacija, tad tvarkykite jį kaip įprastą šaką, o ne kaip pagautą klaidą.

Rezultato stilius vietoj svetimos sąsajos įterpimo

Kadangi aukščiau pateiktas valdiklis yra tiesiog fetch iškvietimas į jūsų pačių DOM, kiekvienas pikselis priklauso jums. Įprastas modelis – trys vaizdinės būsenos, tiesiogiai atvaizduojamos pagal atsakymą:

  • Patikrinta – žalia varnelė, užrašas „Patikrinta“ ir išdavimo data, stilizuota taip, kad derėtų su jūsų svetainės ženklelių / žymų komponentais.
  • Atšaukta – pritildyta arba raudona būsena, rodanti atšaukimo priežastį, o ne ją slepianti. Ir gavėjams, ir trečiosioms šalims naudingesnis sąžiningas „kodėl“, o ne tylus nesėkmės atvejis.
  • Nerasta – vaizdiškai traktuokite kaip „atšaukta“ (nerodykite netikros sėkmės būsenos), tačiau su kitu tekstu, nes neteisingas ID ir sąmoningas atšaukimas yra skirtingos situacijos tam, kas skaito puslapį.

Nieko iš to nereikalauja komponentų bibliotekos. Pakanka switch pagal verified / revoked / not_found ir trijų CSS klasių.

Talpykla, kad negriautumėte galinio taško užklausomis

Patikrinimo galinis taškas yra viešas ir neautentifikuojamas, o tai reiškia, kad nereikia nerimauti dėl kreditų kainos už užklausą – bet vis tiek tai tinklo apsilankymas kiekvieną kartą įkeliant puslapį, jei kviečiate jį kliento pusėje be talpyklos. Puslapyje, kuris visiems lankytojams rodo tą patį ženklelį (pavyzdžiui, „Patikrinto partnerio“ ženklelis poraštėje), rezultatą talpinkite serverio pusėje trumpam TTL – penkių–penkiolikos minučių visiškai pakanka, nes atšaukimai nėra sparčiai besikeičiantis signalas – o ne gaukite iš naujo per kiekvieną užklausą:

const cache = new Map();
async function verifyAwardCached(awardId, ttlMs = 10 * 60 * 1000) {
  const hit = cache.get(awardId);
  if (hit && Date.now() - hit.at < ttlMs) return hit.result;
  const result = await verifyAward(awardId);
  cache.set(awardId, { result, at: Date.now() });
  return result;
}

Kai valdiklis skirtas kiekvienam lankytojui atskirai (gavėjas įterpia savo pažymėjimą asmeninėje svetainėje), praleiskite talpyklą ir tiesiog kvieskite šviežiai įkeliant puslapį – papildoma užklausa tokiu mastu nereikšminga.

Ką badges.ninja gavėjams jau suteikia

Prieš kurdami visiškai pritaikytą įterpimą, verta žinoti, kas jau yra iš dėžės. Kiekvieno apdovanojimo viešame puslapyje yra paruoštų dalijimosi ir įterpimo fragmentų, kuriuos gavėjai gali tiesiog nukopijuoti, be jokio kodo iš jų pusės:

Public share page with social buttons + embed snippets

Jei jūsų atvejis yra „leisti gavėjui parodyti, kad jo ženklelis tikras“, nuoroda į jo badges.ninja/awards/<guid> puslapį dažnai paprastesnė nei pritaikyto valdiklio kūrimas – tai anksčiau parodytas žmonėms skirtas puslapis, ir jis jau pats atskiria patikrintą nuo atšaukto. Šiame įraše aprašytą pritaikytą valdiklį kurkite tada, kai patikrinimo būseną reikia parodyti jūsų produkto sąsajoje – partnerių kataloge, vidiniame audito skydelyje, įdarbinimo įrankyje, tikrinančiame kandidato nurodytus sertifikatus – kur nukreipimas į kitą svetainę nėra tinkama vartotojo patirtis.

Kodėl ne iframe ar tiekėjo valdiklis?

Kai kurios platformos pateikia fragmentą, pavyzdžiui, <iframe src="https://vendor.example.com/verify-widget">, patikrinimo būsenai įterpti. Jis veikia, bet turi realių kaštų: negalite pakeisti turinio stiliaus, kad derėtų su jūsų svetaine (esate pririšti prie tiekėjo pateikto CSS), jis įveda kryžminės kilmės dokumentą, kurį jūsų Content-Security-Policy turi aiškiai leisti, ir kiekvieną kartą įkeliant puslapį siunčiama užklausa trečiosios šalies iframe serveriui, nesvarbu, ar lankytojui apskritai rūpi patikrinimo būsena. Dviejų iškvietimų fetch valdiklis išvengia visų trijų – tai jūsų DOM, jūsų stilius, ir jis veikia tik tada, kai nusprendžiate jį iškviesti.

Visos patikrinimo grandinės perėjimas

Jei kuriate ką nors išsamesnio nei būsenos valdiklis – pavyzdžiui, audito įrankį, tikrinantį pažymėjimų partiją, ar atitikties ataskaitą – eikite visa grandine, o ne sustokite ties patvirtinimu. Patvirtinimas nurodo badge URL (BadgeClass: pavadinimas, aprašymas, kriterijai), o BadgeClass savo ruožtu nurodo issuer URL (organizacijos profilį). Griežtas tikrintuvas išsprendžia visus tris ir patvirtina, kad jie tarpusavyje nuosekliai susiję – ženklelis tikrai priklauso jį nurodančiam išdavėjui, patvirtinimas tikrai nurodo ženklelį, kurį teigia – o ne tik tai, kad aukščiausio lygio patvirtinimas grąžina 200. Tai daugiau gylio nei reikia vieno pažymėjimo būsenos valdikliui, bet verta žinoti, kad tokia struktūra egzistuoja, jei partneris ar auditorius kada nors paklaus: „Kiek giliai iš tikrųjų eina jūsų patikrinimas?“

Dažniausios klaidos, kurių verta vengti

  • Tikrinimas tik pagal HTTP būseną. Kaip minėta aukščiau, atšauktas patvirtinimas vis tiek pasiekiamas. Visada skaitykite assertion.revoked, nenuspręskite dėl patikrinimo vien pagal būsenos kodą.
  • Apdovanojimo ID įrašymas tiesiai į bendrą komponentą. Jei valdiklis skirtas naudoti daugelio gavėjų puslapiuose, apdovanojimo ID imkite kaip parametrą (data atributą, užklausos eilutę, prop), o ne kaip į skriptą įrašytą konstantą.
  • Tylus tinklo klaidų nurijimas. try/catch, kuris nieko neįrašo ir rodo tą patį „nerasta“ tekstą kaip tikrai neegzistuojančiam ženkleliui, vėliau apsunkina derinimą. Atskirkite „tinklo užklausa nepavyko“ nuo „API pasakė ne“ savo klaidų šakose, bent žurnaluose.
  • Pakartotinis tikrinimas per kiekvieną perpiešimą kliento programoje. Jei valdiklis yra React ar Vue komponente, kuris dažnai perpiešiamas, tikrinkite kartą per prijungimą (arba kartą per talpyklos TTL langą, kaip aprašyta talpyklos skyriuje), o ne per kiekvieną perpiešimą.

Ar tai kainuoja kreditus ir ar veikia nemokamame plane?

Ne. Patikrinimo galinis taškas sąmoningai nepatenka į kreditų sistemą, reguliuojančią išdavimą – ženklelio galiojimo tikrinimas išdavėjui nieko nekainuoja ir kviečiančiam lankytojui nereikia nei paskyros, nei API rakto, nei jokio plano lygio. Tai tiesa nepaisant to, ar ženklelis išduotas Free, Starter ar Pro plane: patikrinimas yra paties pažymėjimo savybė, o ne funkcija, apribota išdavėjo prenumerata. Todėl šį valdiklį galite saugiai dėti viešame puslapyje su nenuspėjamu srautu (karjeros puslapyje, partnerių kataloge) nesirūpindami su jūsų paskyra susietais užklausų apribojimais – kreipiatės į tik skaitomą viešą galinį tašką, o ne į autentifikuojamą API maršrutą.

Verta aiškiai pasakyti ir štai ką: galinio taško grąžinamame patvirtinimo JSON nėra gavėjo neapdoroto el. pašto adreso. Gavėjo el. paštas saugomas užšifruotas (hash) serverio pusėje būtent tam, kad iš viešo patikrinimo atsakymo nebūtų galima nuskaityti asmeninės kontaktinės informacijos – gaunate pakankamai pažymėjimui patvirtinti (ženklelis, išdavėjas, datos, atšaukimo būsena), nepaversdami galinio taško potencialių klientų rinkimo įrankiu bet kam, kas pereina apdovanojimų ID.

Pasiruošę išduoti pirmąjį patikrinamą pažymėjimą?

Pradėkite nemokamai badges.ninja – vizualus dizaineris, viešas patikrinimo puslapis, PDF sertifikatas, Open Badge v2.0 išvestis. Kredito kortelės nereikia.

Visą anotuotą kiekvieno patvirtinimo lauko struktūrą rasite JSON-LD laukų žinyne. O jei pažymėjimus išduodate programiškai, o ne tik tikrinate, API greitasis startas aprėpia autentifikavimą ir apdovanojimo sukūrimo iškvietimą, iš kurio atsiranda šio galinio taško išvestis.

Nacho Coll

Apie autorių

Founder & Engineer at Badges Ninja

Nacho founded Badges Ninja to make issuing verifiable digital credentials as simple as a single API call — Open Badge v2.0 badges and certificates, minted, hosted, and verifiable without standing up your own issuer infrastructure. Writes about the Open Badges spec, credential verification, and running a credentialing platform serverless on AWS, from the operator side of the wire.

Grįžti į Tinklaraštį

Susiję straipsniai