Oktatóanyag: Hitelesítés és engedélyek hozzáadása az alkalmazáshoz az Azure Web PubSub használatakor

A csevegőalkalmazás létrehozása során megtanulta, hogyan küldhet és fogadhat adatokat a WebSocket API-k használatával az Azure Web PubSub használatával. Láthatja, hogy az egyszerűség kedvéért nem igényel hitelesítést. Bár az Azure Web PubSub használatához hozzáférési jogkivonatra van szükség, az negotiate oktatóanyagban a hozzáférési jogkivonat létrehozásához használt API-nak nincs szüksége hitelesítésre. Bárki meghívhatja ezt az API-t egy hozzáférési jogkivonat lekéréséhez.

Egy valós alkalmazásban általában azt szeretné, hogy a felhasználó jelentkezzen be először, mielőtt használhatják az alkalmazást. Ebben az oktatóanyagban megtudhatja, hogyan integrálhatja a Web PubSubot az alkalmazás hitelesítési és engedélyezési rendszerével, hogy biztonságosabbá tegye azt.

Az oktatóanyag teljes kódmintáját a GitHubon találja.

Ebben az oktatóanyagban az alábbiakkal fog megismerkedni:

  • GitHub-hitelesítés engedélyezése
  • Hitelesítési köztes szoftver hozzáadása az alkalmazáshoz
  • Engedélyek hozzáadása az ügyfelekhez

Hitelesítés hozzáadása a csevegőszoba alkalmazáshoz

Ez az oktatóanyag újra felhasználja a csevegőalkalmazás létrehozása során létrehozott csevegőalkalmazást. A csevegőalkalmazás teljes kódmintáját a GitHubról is klónozhatja.

Ebben az oktatóanyagban hitelesítést ad hozzá a csevegőalkalmazáshoz, és integrálja azt a Web PubSub szolgáltatással.

Először adja hozzá a GitHub-hitelesítést a csevegőszobához, hogy a felhasználó gitHub-fiókkal jelentkezzen be.

  1. Telepítse a függőségeket.

    npm install --save cookie-parser
    npm install --save express-session
    npm install --save passport
    npm install --save passport-github2
    
  2. Keresse meg a fájlt a server.js címtárban, és engedélyezze a GitHub-hitelesítést a következő kód server.jshozzáadásával:

    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: '/' }));
    

    Az előző kód a Passport.js használatával engedélyezi a GitHub-hitelesítést. Íme egy egyszerű illusztráció a működésről:

    1. /auth/github github.com a bejelentkezéshez.
    2. A bejelentkezés után a GitHub átirányítja Önt /auth/github/callback egy kóddal az alkalmazáshoz a hitelesítés befejezéséhez. (A GitHubról visszaadott profil ellenőrzésének és a kiszolgálón való megőrzésének módját a következőben tekintheti meg: ellenőrzött visszahívás passport.use().)
    3. A hitelesítés befejezése után a rendszer átirányítja a webhely kezdőlapjára (/).

    A GitHub OAuth-ról és a Passport.js-ről a következő cikkekben talál további információt:

    Ennek teszteléséhez először létre kell hoznia egy GitHub OAuth-alkalmazást:

    1. https://www.github.comNyissa meg a profilt, és válassza a Gépház> Developer-beállításokat.
    2. Nyissa meg az OAuth-alkalmazásokat, és válassza az Új OAuth-alkalmazás lehetőséget.
    3. Adja meg az alkalmazás nevét és a kezdőlap URL-címét (az URL-cím bármilyen lehet), és állítsa be az engedélyezési visszahívási URL-címet a következőre http://localhost:8080/auth/github/callback: . Ez az URL-cím megegyezik a kiszolgálón közzétett visszahívási API-val.
    4. Az alkalmazás regisztrálása után másolja ki az ügyfél-azonosítót, és válassza az Új ügyfélkód létrehozása lehetőséget.

    Futtassa az alábbi parancsot a beállítások teszteléséhez, ne felejtse el lecserélni <connection-string>a beállításokat <client-id>és <client-secret> az értékeket.

    export WebPubSubConnectionString="<connection-string>"
    export GitHubClientId="<client-id>"
    export GitHubClientSecret="<client-secret>"
    node server
    

    Most nyissa meg a elemet http://localhost:8080/auth/github. A rendszer átirányítja a GitHubra a bejelentkezéshez. A bejelentkezés után a rendszer átirányítja a csevegőalkalmazásba.

  3. Frissítse a csevegőszobát a GitHubról kapott identitás használatára ahelyett, hogy felhasználónevet kér a felhasználótól.

    Frissítés public/index.html közvetlen hívásra /negotiate felhasználói azonosító megadása nélkül.

    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);
    

    Amikor egy felhasználó bejelentkezik, a kérés automatikusan egy cookie-on keresztül hordozza a felhasználó identitását. Ezért csak ellenőriznie kell, hogy a felhasználó létezik-e az req objektumban, és hozzá kell adnia a felhasználónevet a Web PubSub hozzáférési jogkivonathoz:

    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
      });
    });
    

    Most futtassa újra a kiszolgálót, és megjelenik egy "nem engedélyezett" üzenet a csevegőszoba első megnyitásakor. Válassza ki a bejelentkezési hivatkozást a bejelentkezéshez, majd láthatja, hogy az a korábbiakhoz hasonlóan működik.

Engedélyekkel végzett munka

Az előző oktatóanyagokban megtanulhatta, hogyan tehet WebSocket.send() közzé közvetlenül üzeneteket más ügyfelek számára a subprotocol használatával. Egy valós alkalmazásban előfordulhat, hogy nem szeretné, hogy az ügyfél engedélyvezérlés nélkül közzétehessen vagy előfizethessen egy csoportra. Ebben a szakaszban megtudhatja, hogyan vezérelheti az ügyfeleket a Web PubSub engedélyrendszerével.

A Web PubSubban az ügyfél a következő típusú műveleteket hajthatja végre a subprotocol használatával:

  • Események küldése a kiszolgálóra.
  • Üzenetek közzététele egy csoportban.
  • Csatlakozzon (iratkozzon fel) egy csoportra.

Az ügyfél alapértelmezett művelete, hogy eseményt küld a kiszolgálónak. Nincs protokoll, ezért mindig engedélyezett. Egy csoport közzétételéhez és előfizetéséhez az ügyfélnek engedélyt kell kérnie. A kiszolgáló kétféleképpen adhat engedélyt az ügyfeleknek:

  • Szerepkörök megadása egy ügyfél csatlakoztatásakor (a szerepkör egy olyan fogalom, amely a kezdeti engedélyeket jelöli, amikor egy ügyfél csatlakozik).
  • Api használatával engedélyt adhat egy ügyfélnek a csatlakozás után.

A csoporthoz való csatlakozáshoz az ügyfélnek továbbra is csatlakoznia kell a csoporthoz az "illesztés csoport" üzenet használatával, miután megkapja az engedélyt. Másik lehetőségként a kiszolgáló api-val is hozzáadhatja az ügyfelet egy csoporthoz, még akkor is, ha nem rendelkezik csatlakozási engedéllyel.

Most használjuk ezt az engedélyrendszert egy új funkció hozzáadásához a csevegőszobához. Új, rendszergazda nevű felhasználótípust vehet fel a csevegőszobába. Lehetővé teszi a rendszergazda számára, hogy közvetlenül az ügyfélről küldjön rendszerüzeneteket ("[SYSTEM]" kezdetű üzeneteket).

Először két különböző csoportra kell különítenie a rendszer- és felhasználói üzeneteket, hogy külön szabályozhassa az engedélyeiket.

Módosítsa server.js , hogy különböző üzeneteket küldjön különböző csoportoknak:

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();
  }
});

Az előző kód az WebPubSubServiceClient.group().sendToAll() üzenetet a központ helyett egy csoportnak küldi el.

Mivel az üzenet most már csoportoknak érkezik, ügyfeleket kell hozzáadnia a csoportokhoz, hogy továbbra is fogadhassák az üzeneteket. handleConnect A kezelő használatával ügyfeleket adhat hozzá a csoportokhoz.

Megjegyzés:

handleConnect akkor aktiválódik, ha egy ügyfél a Web PubSubhoz próbál csatlakozni. Ebben a kezelőben csoportokat és szerepköröket adhat vissza, így a szolgáltatás a kapcsolat létrejötte után felvehet kapcsolatot a csoportokhoz, vagy szerepköröket adhat hozzá. A szolgáltatás a kapcsolat megtagadására is használható res.fail() .

Az aktiváláshoz handleConnectnyissa meg az Eseménykezelő beállításait az Azure Portalon, és válassza a csatlakozás lehetőséget a rendszereseményekben.

Az ügyfél HTML-kódját is frissítenie kell, mert most a kiszolgáló egyszerű szöveg helyett JSON-üzeneteket küld:

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 = '';
});

Ezután módosítsa az ügyfélkódot úgy, hogy a rendszercsoportnak küldjön, amikor a felhasználók a rendszerüzenetet választják:

<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>

Alapértelmezés szerint az ügyfélnek nincs engedélye arra, hogy egy csoportnak is küldjön. Frissítse a kiszolgáló kódját a rendszergazdai felhasználó engedélyének megadásához (az egyszerűség kedvéért a rendszergazda azonosítója parancssori argumentumként van megadva).

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);
});

Most futtassa a következőt node server <admin-id>: Láthatja, hogy rendszerüzenetet küldhet minden ügyfélnek, amikor bejelentkezik.<admin-id>

Ha azonban másik felhasználóként jelentkezik be, a rendszerüzenet kiválasztásakor semmi sem történik. Előfordulhat, hogy a szolgáltatás hibaüzenetet ad Önnek, és tudatja Önvel, hogy a művelet nem engedélyezett. Ha visszajelzést szeretne küldeni, beállíthatja ackId , hogy mikor teszi közzé az üzenetet. Amikor ackId meg van adva, a Web PubSub egy egyezést ackId tartalmazó üzenetet ad vissza, amely jelzi, hogy a művelet sikeres volt-e.

Módosítsa a rendszerüzenet küldésének kódját a következő kódra:

let ackId = 0;
system.addEventListener('click', e => {
  ws.send(JSON.stringify({
    type: 'sendToGroup',
    group: 'system',
    ackId: ++ackId,
    dataType: 'text',
    data: message.value
    }));
  message.value = '';
});

Az üzenetek feldolgozásának kódját is módosíthatja az üzenetek kezelésére ack :

ws.onmessage = event => {
  ...
  switch (message.type) {
    case 'ack':
      if (!message.success && message.error.name === 'Forbidden') m.innerText = 'No permission to send system message';
      break;
  }
};

Most futtassa újra a kiszolgálót, és jelentkezzen be másik felhasználóként. Hibaüzenet jelenik meg, amikor rendszerüzenetet próbál küldeni.

Az oktatóanyag teljes kódmintája a GitHubon található.

További lépések

Ez az oktatóanyag bemutatja, hogyan csatlakozhat a Web PubSub szolgáltatáshoz, és hogyan tehet közzé üzeneteket a csatlakoztatott ügyfelek számára a subprotocol használatával.

A Web PubSub szolgáltatás használatával kapcsolatos további információkért olvassa el a dokumentációban elérhető további oktatóanyagokat.