Kurz: Přidání ověřování a oprávnění do aplikace při použití azure Web PubSub
V části Vytvoření chatovací aplikace jste zjistili, jak pomocí rozhraní WebSocket API odesílat a přijímat data pomocí azure Web PubSub. Všimněte si, že kvůli jednoduchosti nevyžaduje žádné ověřování. I když Azure Web PubSub vyžaduje připojení přístupového tokenu, negotiate
rozhraní API použité v kurzu k vygenerování přístupového tokenu nepotřebuje ověřování. Toto rozhraní API může volat kdokoli, aby získal přístupový token.
V reálné aplikaci obvykle chcete, aby se uživatel nejdřív přihlásil, než bude moct aplikaci používat. V tomto kurzu se dozvíte, jak integrovat Web PubSub s ověřovacím a autorizačním systémem vaší aplikace, aby byl bezpečnější.
Kompletní ukázku kódu tohoto kurzu najdete na GitHubu.
V tomto kurzu se naučíte:
- Povolení ověřování GitHubu
- Přidání middlewaru ověřování do aplikace
- Přidání oprávnění klientům
Důležité
Nezpracované připojovací řetězec se v tomto článku zobrazují jenom pro demonstrační účely.
Připojovací řetězec obsahuje informace o autorizaci vyžadované pro vaši aplikaci pro přístup ke službě Azure Web PubSub. Přístupový klíč uvnitř připojovací řetězec je podobný kořenovému heslu pro vaši službu. V produkčních prostředích vždy chraňte přístupové klíče. Pomocí služby Azure Key Vault můžete bezpečně spravovat a obměňovat klíče a zabezpečit připojení WebPubSubServiceClient
.
Vyhněte se distribuci přístupových klíčů ostatním uživatelům, jejich pevnému kódování nebo jejich uložení kdekoli ve formátu prostého textu, který je přístupný ostatním uživatelům. Otočte klíče, pokud se domníváte, že mohly být ohroženy.
Přidání ověřování do aplikace chatovací místnosti
Tento kurz znovu použije chatovací aplikaci vytvořenou v aplikaci Pro sestavení chatu. Kompletní ukázku kódu pro chatovací aplikaci můžete také naklonovat z GitHubu.
V tomto kurzu přidáte do chatovací aplikace ověřování a integrujete ji s web pubSub.
Nejprve do chatovací místnosti přidejte ověřování GitHubu, aby se uživatel mohl přihlásit pomocí účtu GitHubu.
Nainstalujte závislosti.
npm install --save cookie-parser npm install --save express-session npm install --save passport npm install --save passport-github2
server.js
Vyhledejte soubor v adresáři a povolte ověřování GitHubu přidáním následujícího kódu doserver.js
:const app = express(); const users = {}; passport.use( new GitHubStrategy({ clientID: process.argv[3], clientSecret: process.argv[4] }, (accessToken, refreshToken, profile, done) => { users[profile.id] = profile; return done(null, profile); } )); passport.serializeUser((user, done) => { done(null, user.id); }); passport.deserializeUser((id, done) => { if (users[id]) return done(null, users[id]); return done(`invalid user id: ${id}`); }); app.use(cookieParser()); app.use(session({ resave: false, saveUninitialized: true, secret: 'keyboard cat' })); app.use(passport.initialize()); app.use(passport.session()); app.get('/auth/github', passport.authenticate('github', { scope: ['user:email'] })); app.get('/auth/github/callback', passport.authenticate('github', { successRedirect: '/' }));
Předchozí kód používá Passport.js k povolení ověřování GitHubu. Tady je jednoduchý obrázek toho, jak funguje:
/auth/github
se přesměruje na github.com pro přihlášení.- Jakmile se přihlásíte, GitHub vás přesměruje na kód, na
/auth/github/callback
který vaše aplikace dokončí ověřování. (Pokud chcete zjistit, jak je profil vrácený z GitHubu ověřený a trvalý na serveru, podívejte se na ověřené zpětné volání vpassport.use()
souboru .) - Po dokončení ověřování budete přesměrováni na domovskou stránku (
/
) webu.
Další podrobnosti o OAuth a Passport.js GitHubu najdete v následujících článcích:
K otestování je potřeba nejprve vytvořit aplikaci GitHub OAuth:
- Přejděte na https://www.github.com, otevřete svůj profil a vyberte Nastavení>pro vývojáře nastavení.
- Přejděte do aplikací OAuth a vyberte Nová aplikace OAuth.
- Vyplňte název aplikace a adresu URL domovské stránky (adresa URL může být cokoli, co se vám líbí) a nastavte adresu URL zpětného volání autorizace na
http://localhost:8080/auth/github/callback
hodnotu . Tato adresa URL odpovídá rozhraní API zpětného volání, které jste odhalili na serveru. - Po registraci aplikace zkopírujte ID klienta a vyberte Vygenerovat nový tajný klíč klienta.
Nezpracované připojovací řetězec se v tomto článku zobrazují jenom pro demonstrační účely. V produkčních prostředích vždy chraňte přístupové klíče. Pomocí služby Azure Key Vault můžete bezpečně spravovat a obměňovat klíče a zabezpečit připojení
WebPubSubServiceClient
.Spuštěním následujícího příkazu otestujte nastavení, nezapomeňte nahradit
<connection-string>
<client-id>
, a<client-secret>
s vašimi hodnotami.export WebPubSubConnectionString="<connection-string>" export GitHubClientId="<client-id>" export GitHubClientSecret="<client-secret>" node server
Nyní otevřete
http://localhost:8080/auth/github
. Budete přesměrováni na GitHub, abyste se mohli přihlásit. Po přihlášení budete přesměrováni do chatovací aplikace.Aktualizujte chatovací místnost tak, aby používala identitu, kterou získáte z GitHubu, místo výzvy uživatele k zadání uživatelského jména.
Umožňuje aktualizovat
public/index.html
přímé volání/negotiate
bez předání ID uživatele.let messages = document.querySelector('#messages'); let res = await fetch(`/negotiate`); if (res.status === 401) { let m = document.createElement('p'); m.innerHTML = 'Not authorized, click <a href="/auth/github">here</a> to login'; messages.append(m); return; } let data = await res.json(); let ws = new WebSocket(data.url);
Když je uživatel přihlášený, požadavek automaticky přenese identitu uživatele prostřednictvím souboru cookie. Stačí zkontrolovat, jestli uživatel v objektu
req
existuje, a přidat uživatelské jméno do přístupového tokenu Web PubSub:app.get('/negotiate', async (req, res) => { if (!req.user || !req.user.username) { res.status(401).send('missing user id'); return; } let options = { userId: req.user.username }; let token = await serviceClient.getClientAccessToken(options); res.json({ url: token.url }); });
Teď znovu spusťte server a při prvním otevření chatovací místnosti se zobrazí zpráva , že není autorizovaný. Vyberte přihlašovací odkaz, který chcete přihlásit, a pak uvidíte, že funguje jako předtím.
Práce s oprávněními
V předchozích kurzech jste se naučili používat WebSocket.send()
přímé publikování zpráv do jiných klientů pomocí subprotocolu. Ve skutečné aplikaci možná nebudete chtít, aby klient mohl publikovat nebo přihlásit k odběru jakékoli skupiny bez řízení oprávnění. V této části se dozvíte, jak řídit klienty pomocí systému oprávnění web pubSub.
V podsítě Web PubSub může klient provádět následující typy operací s dílčím souhrnem:
- Odesílání událostí na server
- Publikování zpráv do skupiny
- Připojte se (přihlaste se k odběru) skupiny.
Odeslání události na server je výchozí operací klienta. Nepoužívá se žádný protokol, takže je vždy povolený. Pokud chcete publikovat a přihlásit se k odběru skupiny, klient musí získat oprávnění. Server může udělit oprávnění klientům dvěma způsoby:
- Určete role, když je klient připojený (role představuje koncept představující počáteční oprávnění při připojení klienta).
- Pomocí rozhraní API udělte klientovi oprávnění po připojení.
Aby se klient mohl ke skupině připojit, musí se ke skupině připojit pomocí zprávy "Join group" (Skupina připojení), jakmile získá oprávnění. Případně může server použít rozhraní API k přidání klienta do skupiny, i když nemá oprávnění k připojení.
Teď použijeme tento systém oprávnění k přidání nové funkce do chatovací místnosti. Do chatovací místnosti přidáte nový typ uživatele s názvem správce . Správci povolíte odesílat systémové zprávy (zprávy začínající na "[SYSTEM]") přímo z klienta.
Nejprve je potřeba oddělit systémové a uživatelské zprávy do dvou různých skupin, abyste mohli řídit svá oprávnění samostatně.
Změna server.js
pro odesílání různých zpráv do různých skupin:
let handler = new WebPubSubEventHandler(hubName, {
path: '/eventhandler',
handleConnect: (req, res) => {
res.success({
groups: ['system', 'message'],
});
},
onConnected: req => {
console.log(`${req.context.userId} connected`);
serviceClient.group('system').sendToAll(`${req.context.userId} joined`, { contentType: 'text/plain' });
},
handleUserEvent: (req, res) => {
if (req.context.eventName === 'message') {
serviceClient.group('message').sendToAll({
user: req.context.userId,
message: req.data
});
}
res.success();
}
});
Předchozí kód používá WebPubSubServiceClient.group().sendToAll()
k odeslání zprávy do skupiny místo centra.
Protože se teď zpráva odesílá do skupin, musíte do skupin přidat klienty, aby mohli dál přijímat zprávy. Obslužnou rutinu handleConnect
použijte k přidání klientů do skupin.
Poznámka:
handleConnect
se aktivuje, když se klient pokouší připojit k podsítě Web PubSub. V této obslužné rutině můžete vrátit skupiny a role, takže služba může přidat připojení ke skupinám nebo udělit role, jakmile se připojení vytvoří. Služba může také použít res.fail()
k odepření připojení.
Pokud chcete aktivovat handleConnect
, přejděte na webu Azure Portal do nastavení obslužné rutiny události a vyberte připojit se v systémových událostech.
Musíte také aktualizovat kód HTML klienta, protože teď server odesílá zprávy JSON místo prostého textu:
let ws = new WebSocket(data.url, 'json.webpubsub.azure.v1');
ws.onopen = () => console.log('connected');
ws.onmessage = event => {
let m = document.createElement('p');
let message = JSON.parse(event.data);
switch (message.type) {
case 'message':
if (message.group === 'system') m.innerText = `[SYSTEM] ${message.data}`;
else if (message.group === 'message') m.innerText = `[${message.data.user}] ${message.data.message}`;
break;
}
messages.appendChild(m);
};
let message = document.querySelector('#message');
message.addEventListener('keypress', e => {
if (e.charCode !== 13) return;
ws.send(JSON.stringify({
type: 'event',
event: 'message',
dataType: 'text',
data: message.value
}));
message.value = '';
});
Potom změňte kód klienta tak, aby se odeslal systémové skupině, když uživatelé vyberou systémovou zprávu:
<button id="system">system message</button>
...
<script>
(async function() {
...
let system = document.querySelector('#system');
system.addEventListener('click', e => {
ws.send(JSON.stringify({
type: 'sendToGroup',
group: 'system',
dataType: 'text',
data: message.value
}));
message.value = '';
});
})();
</script>
Ve výchozím nastavení nemá klient oprávnění k odesílání do žádné skupiny. Aktualizujte kód serveru tak, aby uživateli s právy správce udělil oprávnění (pro jednoduchost je ID správce poskytováno jako argument příkazového řádku).
app.get('/negotiate', async (req, res) => {
...
if (req.user.username === process.argv[2]) options.claims = { role: ['webpubsub.sendToGroup.system'] };
let token = await serviceClient.getClientAccessToken(options);
});
Nyní spusťte node server <admin-id>
. Vidíte, že můžete odeslat systémovou zprávu každému klientovi, když se přihlásíte jako <admin-id>
.
Pokud se ale přihlásíte jako jiný uživatel, při výběru systémové zprávy se nic nestane. Můžete očekávat, že služba zobrazí chybu, abyste věděli, že operace není povolená. Pokud chcete poskytnout tuto zpětnou vazbu, můžete ji nastavit ackId
při publikování zprávy. Při každém ackId
zadání vrátí web pubSub zprávu s odpovídajícími informacemi ackId
o tom, jestli operace proběhla úspěšně nebo ne.
Změňte kód odeslání systémové zprávy na následující kód:
let ackId = 0;
system.addEventListener('click', e => {
ws.send(JSON.stringify({
type: 'sendToGroup',
group: 'system',
ackId: ++ackId,
dataType: 'text',
data: message.value
}));
message.value = '';
});
Změňte také kód zpracování zpráv tak, aby zpracovával ack
zprávu:
ws.onmessage = event => {
...
switch (message.type) {
case 'ack':
if (!message.success && message.error.name === 'Forbidden') m.innerText = 'No permission to send system message';
break;
}
};
Teď znovu spusťte server a přihlaste se jako jiný uživatel. Při pokusu o odeslání systémové zprávy se zobrazí chybová zpráva.
Kompletní ukázka kódu tohoto kurzu najdete na GitHubu.
Další kroky
V tomto kurzu získáte základní představu o tom, jak se připojit ke službě Web PubSub a jak publikovat zprávy do připojených klientů pomocí subprotocolu.
Další informace o používání služby Web PubSub najdete v dalších kurzech dostupných v dokumentaci.