Zelfstudie: Verificatie en machtigingen toevoegen aan uw toepassing wanneer u Azure Web PubSub gebruikt
In Een chat-app bouwen hebt u geleerd hoe u WebSocket-API's gebruikt voor het verzenden en ontvangen van gegevens met Azure Web PubSub. U ziet dat voor het gemak geen verificatie vereist is. Hoewel Azure Web PubSub vereist dat een toegangstoken is verbonden, heeft de negotiate
API die in de zelfstudie wordt gebruikt om het toegangstoken te genereren geen verificatie nodig. Iedereen kan deze API aanroepen om een toegangstoken op te halen.
In een echte toepassing wilt u doorgaans dat de gebruiker zich eerst aanmeldt voordat deze uw toepassing kan gebruiken. In deze zelfstudie leert u hoe u Web PubSub integreert met het verificatie- en autorisatiesysteem van uw toepassing om deze veiliger te maken.
U vindt het volledige codevoorbeeld van deze zelfstudie op GitHub.
In deze zelfstudie leert u het volgende:
- GitHub-verificatie inschakelen
- Verificatie-middleware toevoegen aan uw toepassing
- Machtigingen toevoegen aan de clients
Belangrijk
Onbewerkte verbindingsreeks worden alleen in dit artikel weergegeven voor demonstratiedoeleinden.
Een verbindingsreeks bevat de autorisatiegegevens die nodig zijn voor uw toepassing voor toegang tot de Azure Web PubSub-service. De toegangssleutel in de verbindingsreeks is vergelijkbaar met een hoofdwachtwoord voor uw service. Beveilig uw toegangssleutels altijd in productieomgevingen. Gebruik Azure Key Vault om uw sleutels veilig te beheren en te roteren en uw verbinding te beveiligen.WebPubSubServiceClient
Vermijd het distribueren van toegangssleutels naar andere gebruikers, het coderen ervan of het opslaan van ze ergens in tekst zonder opmaak die toegankelijk is voor anderen. Draai uw sleutels als u denkt dat ze mogelijk zijn aangetast.
Verificatie toevoegen aan de chatruimte-app
In deze zelfstudie wordt de chattoepassing die is gemaakt in een chat-app, opnieuw gebruikt. U kunt ook het volledige codevoorbeeld voor de chat-app klonen vanuit GitHub.
In deze zelfstudie voegt u verificatie toe aan de chattoepassing en integreert u deze met Web PubSub.
Voeg eerst GitHub-verificatie toe aan de chatruimte, zodat de gebruiker een GitHub-account kan gebruiken om zich aan te melden.
Installeer afhankelijkheden.
npm install --save cookie-parser npm install --save express-session npm install --save passport npm install --save passport-github2
Zoek het
server.js
bestand in uw map en schakel GitHub-verificatie in door de volgende code toe te voegen aanserver.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: '/' }));
In de voorgaande code wordt Passport.js gebruikt om GitHub-verificatie in te schakelen. Hier volgt een eenvoudige illustratie van hoe het werkt:
/auth/github
wordt omgeleid naar github.com voor aanmelding.- Nadat u zich hebt aangemeld, wordt u door GitHub omgeleid met
/auth/github/callback
een code voor uw toepassing om de verificatie te voltooien. (Zie de geverifieerde callback inpassport.use()
.) als u wilt zien hoe het profiel dat wordt geretourneerd vanuit GitHub is geverifieerd en persistent is op de server. - Nadat de verificatie is voltooid, wordt u omgeleid naar de startpagina (
/
) van de site.
Zie de volgende artikelen voor meer informatie over GitHub OAuth en Passport.js:
Als u dit wilt testen, moet u eerst een GitHub OAuth-app maken:
- Ga naarhttps://www.github.com, open uw profiel en selecteer Instellingen> voor ontwikkelaars.
- Ga naar OAuth-apps en selecteer Nieuwe OAuth-app.
- Vul de naam en startpagina-URL van de toepassing in (de URL kan alles zijn wat u wilt) en stel de callback-URL voor autorisatie in op
http://localhost:8080/auth/github/callback
. Deze URL komt overeen met de callback-API die u op de server hebt weergegeven. - Nadat de toepassing is geregistreerd, kopieert u de client-id en selecteert u Een nieuw clientgeheim genereren.
Onbewerkte verbindingsreeks worden alleen in dit artikel weergegeven voor demonstratiedoeleinden. Beveilig uw toegangssleutels altijd in productieomgevingen. Gebruik Azure Key Vault om uw sleutels veilig te beheren en te roteren en uw verbinding te beveiligen.
WebPubSubServiceClient
Voer de onderstaande opdracht uit om de instellingen te testen, vergeet niet om te vervangen
<connection-string>
en<client-secret>
<client-id>
door uw waarden.export WebPubSubConnectionString="<connection-string>" export GitHubClientId="<client-id>" export GitHubClientSecret="<client-secret>" node server
http://localhost:8080/auth/github
Open nu . U wordt omgeleid naar GitHub om u aan te melden. Nadat u zich hebt aangemeld, wordt u omgeleid naar de chattoepassing.Werk de chatruimte bij om gebruik te maken van de identiteit die u van GitHub krijgt, in plaats van de gebruiker om een gebruikersnaam te vragen.
Werk
public/index.html
bij om rechtstreeks aan te roepen/negotiate
zonder een gebruikers-id door te geven.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);
Wanneer een gebruiker is aangemeld, draagt de aanvraag automatisch de identiteit van de gebruiker via een cookie. U hoeft dus alleen te controleren of de gebruiker bestaat in het
req
object en de gebruikersnaam toe te voegen aan het Web PubSub-toegangstoken: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 }); });
Voer de server nu opnieuw uit en u ziet het bericht 'niet geautoriseerd' voor de eerste keer dat u de chatruimte opent. Selecteer de aanmeldingskoppeling om u aan te melden en u ziet dat deze werkt zoals voorheen.
Werken met machtigingen
In de vorige zelfstudies hebt u geleerd om WebSocket.send()
berichten rechtstreeks naar andere clients te publiceren met behulp van subprotocol. In een echte toepassing wilt u mogelijk niet dat de client een groep kan publiceren of abonneren zonder machtigingsbeheer. In deze sectie ziet u hoe u clients kunt beheren met behulp van het machtigingssysteem van Web PubSub.
In Web PubSub kan een client de volgende typen bewerkingen uitvoeren met subprotocol:
- Gebeurtenissen verzenden naar de server.
- Berichten publiceren naar een groep.
- Neem deel aan een groep (abonneer u op).
Het verzenden van een gebeurtenis naar de server is de standaardbewerking van de client. Er wordt geen protocol gebruikt, dus dit is altijd toegestaan. Voor het publiceren en abonneren op een groep moet de client toestemming krijgen. Er zijn twee manieren waarop de server machtigingen kan verlenen aan clients:
- Geef rollen op wanneer een client is verbonden (rol is een concept dat de eerste machtigingen vertegenwoordigt wanneer een client is verbonden).
- Gebruik een API om toestemming te verlenen aan een client nadat deze is verbonden.
Als u toestemming wilt geven om lid te worden van een groep, moet de client nog steeds lid worden van de groep met behulp van het bericht 'Deelnemen aan groep' nadat de machtiging is opgehaald. De server kan ook een API gebruiken om de client toe te voegen aan een groep, zelfs als deze niet over de joinmachtiging beschikt.
Nu gaan we dit machtigingssysteem gebruiken om een nieuwe functie toe te voegen aan de chatruimte. U voegt een nieuw type gebruiker met de naam Beheerder toe aan de chatruimte. U staat de beheerder toe om systeemberichten (berichten die beginnen met [SYSTEM]) rechtstreeks vanaf de client te verzenden.
Eerst moet u systeem- en gebruikersberichten scheiden in twee verschillende groepen, zodat u hun machtigingen afzonderlijk kunt beheren.
Wijzigen server.js
om verschillende berichten naar verschillende groepen te verzenden:
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();
}
});
De voorgaande code gebruikt WebPubSubServiceClient.group().sendToAll()
om het bericht naar een groep te verzenden in plaats van de hub.
Omdat het bericht nu naar groepen wordt verzonden, moet u clients toevoegen aan groepen, zodat ze berichten kunnen blijven ontvangen. Gebruik de handleConnect
handler om clients toe te voegen aan groepen.
Notitie
handleConnect
wordt geactiveerd wanneer een client verbinding probeert te maken met Web PubSub. In deze handler kunt u groepen en rollen retourneren, zodat de service een verbinding met groepen kan toevoegen of rollen kan verlenen zodra de verbinding tot stand is gebracht. De service kan ook gebruiken res.fail()
om de verbinding te weigeren.
Als u wilt activeren handleConnect
, gaat u naar de instellingen van de gebeurtenis-handler in Azure Portal en selecteert u verbinding maken in systeemevenementen.
U moet ook de HTML van de client bijwerken, omdat de server nu JSON-berichten verzendt in plaats van tekst zonder opmaak:
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 = '';
});
Wijzig vervolgens de clientcode die naar de systeemgroep wordt verzonden wanneer gebruikers systeembericht selecteren:
<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>
Standaard is de client niet gemachtigd om naar een groep te verzenden. Werk de servercode bij om toestemming te verlenen aan de gebruiker met beheerdersrechten (om het eenvoudig te maken, wordt de id van de beheerder opgegeven als een opdrachtregelargument).
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);
});
Voer nu uit node server <admin-id>
. U ziet dat u een systeembericht naar elke client kunt verzenden wanneer u zich aanmeldt als <admin-id>
.
Maar als u zich aanmeldt als een andere gebruiker, gebeurt er niets wanneer u systeembericht selecteert. U kunt verwachten dat de service u een foutmelding geeft om u te laten weten dat de bewerking niet is toegestaan. Als u deze feedback wilt geven, kunt u instellen ackId
wanneer u het bericht publiceert. Wanneer ackId
dit is opgegeven, retourneert Web PubSub een bericht met een overeenkomst ackId
om aan te geven of de bewerking al dan niet is geslaagd.
Wijzig de code van het verzenden van een systeembericht naar de volgende code:
let ackId = 0;
system.addEventListener('click', e => {
ws.send(JSON.stringify({
type: 'sendToGroup',
group: 'system',
ackId: ++ackId,
dataType: 'text',
data: message.value
}));
message.value = '';
});
Wijzig ook de code voor het verwerken van berichten om een ack
bericht te verwerken:
ws.onmessage = event => {
...
switch (message.type) {
case 'ack':
if (!message.success && message.error.name === 'Forbidden') m.innerText = 'No permission to send system message';
break;
}
};
Voer nu de server opnieuw uit en meld u aan als een andere gebruiker. Er wordt een foutbericht weergegeven wanneer u een systeembericht probeert te verzenden.
Het volledige codevoorbeeld van deze zelfstudie vindt u op GitHub.
Volgende stappen
Deze zelfstudie biedt een basisidee van het maken van verbinding met de Web PubSub-service en het publiceren van berichten naar verbonden clients met behulp van subprotocol.
Lees de andere zelfstudies die beschikbaar zijn in de documentatie voor meer informatie over het gebruik van de Web PubSub-service.