Aracılığıyla paylaş


Öğretici: Azure Web PubSub kullanırken uygulamanıza kimlik doğrulaması ve izin ekleme

Sohbet uygulaması oluşturma bölümünde, Azure Web PubSub ile veri göndermek ve almak için WebSocket API'lerini kullanmayı öğrendiniz. Kolaylık olması için herhangi bir kimlik doğrulaması gerektirmediğini fark edeceksiniz. Azure Web PubSub'un bağlanması için bir erişim belirteci gerektirse de, negotiate erişim belirtecini oluşturmak için öğreticide kullanılan API'nin kimlik doğrulamasına ihtiyacı yoktur. Erişim belirteci almak için herkes bu API'yi çağırabilir.

Gerçek dünyadaki bir uygulamada genellikle kullanıcının uygulamanızı kullanabilmesi için önce oturum açmasını istersiniz. Bu öğreticide, Web PubSub'ı uygulamanızın kimlik doğrulama ve yetkilendirme sistemiyle tümleştirerek daha güvenli hale getirme hakkında bilgi edineceksiniz.

Bu öğreticinin kod örneğinin tamamını GitHub'da bulabilirsiniz.

Bu öğreticide aşağıdakilerin nasıl yapılacağını öğreneceksiniz:

  • GitHub kimlik doğrulamasını etkinleştirme
  • Uygulamanıza kimlik doğrulama ara yazılımı ekleme
  • İstemcilere izin ekleme

Sohbet odası uygulamasına kimlik doğrulaması ekleme

Bu öğreticide, Sohbet uygulaması oluşturma bölümünde oluşturulan sohbet uygulaması yeniden kullanılır. Ayrıca GitHub'dan sohbet uygulaması için tam kod örneğini de kopyalayabilirsiniz.

Bu öğreticide, sohbet uygulamasına kimlik doğrulaması ekleyecek ve Web PubSub ile tümleştireceksiniz.

İlk olarak, kullanıcının oturum açmak için GitHub hesabını kullanabilmesi için sohbet odasına GitHub kimlik doğrulamasını ekleyin.

  1. Bağımlılıkları yükleyin.

    npm install --save cookie-parser
    npm install --save express-session
    npm install --save passport
    npm install --save passport-github2
    
  2. server.js aşağıdaki kodu dizininde bulun ve github kimlik doğrulamasını etkinleştirmek için aşağıdaki kodu ekleyinserver.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: '/' }));
    

    Yukarıdaki kod, GitHub kimlik doğrulamasını etkinleştirmek için Passport.js kullanır. Nasıl çalıştığını gösteren basit bir çizim aşağıdadır:

    1. /auth/github oturum açmak için github.com yönlendirir.
    2. Oturum açtığınızda GitHub, uygulamanızın kimlik doğrulamasını /auth/github/callback tamamlaması için bir kodla sizi adresine yönlendirir. (GitHub'dan döndürülen profilin sunucuda nasıl doğrulanıp kalıcı hale döndürüldiğini görmek için, içinde doğrulanmış geri passport.use()çağırmaya bakın.)
    3. Kimlik doğrulaması tamamlandıktan sonra sitenin giriş sayfasına (/) yönlendirilirsiniz.

    GitHub OAuth ve Passport.js hakkında daha fazla ayrıntı için aşağıdaki makalelere bakın:

    Bunu test etmek için önce bir GitHub OAuth uygulaması oluşturmanız gerekir:

    1. adresine https://www.github.comgidin, profilinizi açın ve Ayarlar> Geldirici ayarları'nı seçin.
    2. OAuth Uygulamaları'na gidin ve Yeni OAuth Uygulaması'nı seçin.
    3. Uygulama adını ve giriş sayfası URL'sini (URL istediğiniz gibi olabilir) doldurun ve Yetkilendirme geri çağırma URL'sini olarak http://localhost:8080/auth/github/callbackayarlayın. Bu URL, sunucuda kullanıma sunulan geri çağırma API'si ile eşleşir.
    4. Uygulama kaydedildikten sonra istemci kimliğini kopyalayın ve Yeni bir istemci gizli dizisi oluştur'a tıklayın.

    Ayarları test etmek için aşağıdaki komutu çalıştırın, , <client-id>ve <client-secret> değerleriniz ile değiştirmeyi <connection-string>unutmayın.

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

    Şimdi dosyasını açın http://localhost:8080/auth/github. Oturum açmak için GitHub'a yönlendirilirsiniz. Oturum açtığınızda sohbet uygulamasına yönlendirilirsiniz.

  3. Kullanıcıdan kullanıcı adı isteme yerine GitHub'dan edindiğiniz kimliği kullanmak için sohbet odasını güncelleştirin.

    Kullanıcı kimliğini geçirmeden doğrudan çağrısına /negotiate güncelleştirinpublic/index.html.

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

    Kullanıcı oturum açtığında, istek kullanıcının kimliğini bir tanımlama bilgisi aracılığıyla otomatik olarak taşır. Bu nedenle, kullanıcının nesnede req var olup olmadığını denetlemeniz ve kullanıcı adını Web PubSub erişim belirtecine eklemeniz yeterlidir:

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

    Şimdi sunucuyu yeniden çalıştırın ve sohbet odasını ilk kez açtığınızda "yetkilendirilmedi" iletisini görürsünüz. Oturum açmak için oturum açma bağlantısını seçin ve daha önce olduğu gibi çalıştığını görürsünüz.

İzinlerle çalışma

Önceki öğreticilerde, altprotocol kullanarak iletileri doğrudan diğer istemcilere yayımlamak için kullanmayı WebSocket.send() öğrendiniz. Gerçek bir uygulamada, istemcinin izin denetimi olmadan herhangi bir grubu yayımlamasını veya abone olmasını istemeyebilirsiniz. Bu bölümde, Web PubSub'un izin sistemini kullanarak istemcilerin nasıl denetlendiğini göreceksiniz.

Web PubSub'da istemci, altprotocol ile aşağıdaki işlem türlerini gerçekleştirebilir:

  • Olayları sunucuya gönderin.
  • İletileri bir gruba yayımlama.
  • Gruba katılın (abone olun).

Sunucuya olay göndermek istemcinin varsayılan işlemidir. Protokol kullanılmaz, bu nedenle her zaman izin verilir. Bir grubu yayımlamak ve gruba abone olmak için istemcinin izin alması gerekir. Sunucunun istemcilere izin vermenin iki yolu vardır:

  • İstemci bağlandığında rolleri belirtin (rol , bir istemci bağlandığında ilk izinleri temsil eden bir kavramdır).
  • Bağlandıktan sonra bir istemciye izin vermek için API kullanın.

Gruba katılma izni için, istemcinin izni aldıktan sonra "gruba katıl" iletisini kullanarak gruba katılması gerekir. Alternatif olarak sunucu, birleştirme izni olmasa bile istemciyi bir gruba eklemek için BIR API kullanabilir.

Şimdi sohbet odasına yeni bir özellik eklemek için bu izin sistemini kullanalım. Sohbet odasına yönetici adlı yeni bir kullanıcı türü eklersiniz. Yöneticinin doğrudan istemciden sistem iletileri ("[SYSTEM]" ile başlayan iletiler) göndermesine izin verirsiniz.

İlk olarak, izinlerini ayrı ayrı denetleyebilmek için sistem ve kullanıcı iletilerini iki farklı gruba ayırmanız gerekir.

Farklı gruplara farklı iletiler göndermek için değiştirin server.js :

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

Yukarıdaki kod, iletiyi hub yerine bir gruba göndermek için kullanır WebPubSubServiceClient.group().sendToAll() .

İleti artık gruplara gönderildiğinden, iletileri almaya devam edebilmeleri için gruplara istemci eklemeniz gerekir. İstemcileri handleConnect gruplara eklemek için işleyiciyi kullanın.

Dekont

handleConnect bir istemci Web PubSub'a bağlanmaya çalıştığında tetikleniyor. Bu işleyicide grupları ve rolleri döndürebilirsiniz; böylece hizmet, bağlantı kurulur kurulmaz gruplara bağlantı ekleyebilir veya roller verebilir. Hizmet, bağlantıyı reddetmek için de kullanabilir res.fail() .

öğesini tetikleme handleConnectiçin Azure portalında olay işleyicisi ayarlarına gidin ve sistem olaylarında bağlan'ı seçin.

Sunucu artık düz metin yerine JSON iletileri gönderdiğinden istemci HTML'sini de güncelleştirmeniz gerekir:

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

Ardından, kullanıcılar sistem iletisini seçtiğinde istemci kodunu sistem grubuna gönderecek şekilde değiştirin:

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

Varsayılan olarak, istemcinin herhangi bir gruba gönderme izni yoktur. Yönetici kullanıcıya izin vermek için sunucu kodunu güncelleştirin (kolaylık olması için, yöneticinin kimliği komut satırı bağımsız değişkeni olarak sağlanır).

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

Şimdi komutunu çalıştırın node server <admin-id>. olarak <admin-id>oturum açtığınızda her istemciye bir sistem iletisi gönderebileceğinizi görürsünüz.

Ancak farklı bir kullanıcı olarak oturum açarsanız, sistem iletisini seçtiğinizde hiçbir şey olmaz. Hizmetin size işleme izin verilmediğinden emin olmak için bir hata vermesini bekleyebilirsiniz. Bu geri bildirimi sağlamak için iletiyi yayımlarken ayarlayabilirsiniz ackId . Her ackId belirtildiğinde, Web PubSub işlemin başarılı olup olmadığını belirtmek için eşleşen ackId bir ileti döndürür.

Sistem iletisi gönderme kodunu aşağıdaki kodla değiştirin:

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

İletiyi işlemek ack için iletileri işleme kodunu da değiştirin:

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

Şimdi sunucuyu yeniden çalıştırın ve farklı bir kullanıcı olarak oturum açın. Sistem iletisi göndermeye çalışırken bir hata iletisi görürsünüz.

Bu öğreticinin tam kod örneği GitHub'da bulunabilir.

Sonraki adımlar

Bu öğretici, Web PubSub hizmetine bağlanma ve altprotocol kullanarak bağlı istemcilere ileti yayımlama hakkında temel bir fikir sağlar.

Web PubSub hizmetini kullanma hakkında daha fazla bilgi edinmek için belgelerde sağlanan diğer öğreticileri okuyun.