Socket.io-client: socket.handshake.queryλ₯Ό ν•¨μˆ˜λ‘œ ν—ˆμš©

에 λ§Œλ“  2017λ…„ 05μ›” 22일  Β·  9μ½”λ©˜νŠΈ  Β·  좜처: socketio/socket.io-client

μ›ν•˜λŠ” μž‘μ—…:

  • [x] 버그 보고
  • [ ] κΈ°λŠ₯ μš”μ²­

ν˜„μž¬ 행동

socket.handshake.query ν˜„μž¬ connect 에 λŒ€ν•œ 데이터 섀정을 ν—ˆμš©ν•˜μ§€λ§Œ reconnect κ°€ μ‹€ν–‰λ˜κΈ° μ „μ—λŠ” 참쑰둜 μ—…λ°μ΄νŠΈν•  수 μ—†μŠ΅λ‹ˆλ‹€. 이것은 μƒˆλ‘œ κ³ μΉ¨ ν† ν°μœΌλ‘œ μ†ŒμΌ“ 연결을 μŠΉμΈν•  λ•Œ 문제λ₯Ό μΌμœΌν‚΅λ‹ˆλ‹€.

μž¬ν˜„ 단계(ν˜„μž¬ λ™μž‘μ΄ 버그인 경우)

//client
io.connect("wss://socket.server.com", {
   query : {
      token:"something dynamic"
   }
});

μ„œλ²„κ°€ λ‹€μ‹œ μ‹œμž‘λ˜κ³  ν΄λΌμ΄μ–ΈνŠΈκ°€ reconnect 인 경우 μ†ŒμΌ“μ„ λ‹€μ‹œ 인증할 λ•Œ 토큰이 μ˜€λž˜λ˜μ—ˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€.

//server
io.use(function(socket, next) {
   var query = socket.handshake.query;
   if(isValidToken(query.token)){
      next();//will never fire if the token has been updated
   }
});

μ˜ˆμƒλ˜λŠ” 행동

쿼리λ₯Ό function :

io.connect("wss://socket.server.com", {
   query : function(){
      return {
         token:"something dynamic"
      }
   }
});

μ„€μ •

  • socket.io 버전: 2.0.1

μ–΄λ–»κ²Œ κ³ μΉ˜λŠ” 지

ν˜„μž¬ μ†ŒμΌ“ μƒμ„±μžμ—μ„œ:

if (opts && opts.query) {
   this.query = opts.query;
}

λ‹€μŒκ³Ό 같이 λ³€κ²½ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

if(opts && opts.query) {
   this.query = typeof opts.query == 'function' && opts.query.call(this) || opts.query;
}

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

@reeltimedoktor ν˜„μž¬ reconnect_attempt μ΄λ²€νŠΈμ—μ„œ query 개체λ₯Ό μ—…λ°μ΄νŠΈν•  수 μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€.

socket.on('reconnect_attempt', function () {
  socket.io.opts.query = { token: /* ... */ };
});

λͺ¨λ“  9 λŒ“κΈ€

+1
버그 #1086에 λŒ€ν•œ μˆ˜μ •λ„ 문제λ₯Ό ν•΄κ²°ν•΄μ•Ό ν•©λ‹ˆλ‹€. 연결에 μ„±κ³΅ν•œ ν›„ 쿼리 μ˜΅μ…˜μ„ λ³€κ²½ν•˜λ©΄ 이전 socket.io-client λ²„μ „μ—μ„œ μž‘λ™ν–ˆμ§€λ§Œ ν˜„μž¬ λ²„μ „μ—μ„œλŠ” 쿼리 κ°œμ²΄μ— λŒ€ν•œ μ°Έμ‘°κ°€ μ†μ‹€λ©λ‹ˆλ‹€.

@reeltimedoktor ν˜„μž¬ reconnect_attempt μ΄λ²€νŠΈμ—μ„œ query 개체λ₯Ό μ—…λ°μ΄νŠΈν•  수 μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€.

socket.on('reconnect_attempt', function () {
  socket.io.opts.query = { token: /* ... */ };
});

@darrachequesne 의 μ†”λ£¨μ…˜μ΄ λ‚˜λ₯Ό μœ„ν•΄ μž‘λ™ν•˜μ§€ μ•ŠλŠ” 것 κ°™μŠ΅λ‹ˆλ‹€ :(

μ €λŠ” socket.io 버전 2.3.0 의 λ…Έλ“œ μ„œλ²„μ™€ ν•¨κ»˜ ν΄λΌμ΄μ–ΈνŠΈμ˜ socket.io-client 버전 2.3.0 에 μžˆμŠ΅λ‹ˆλ‹€.

ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ λ‚˜λŠ” μ΄κ²ƒμ„ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€ :

 socket.on('reconnect_attempt', async () => {
      const newToken = await getNewToken();
      socket.io.opts.query = {
        token: latestToken,
      };
    });

그런 λ‹€μŒ μ„œλ²„λŠ” io.use() μ „λ‹¬λœ 미듀웨어λ₯Ό μ‚¬μš©ν•˜μ—¬ 토큰을 μΈμ¦ν•©λ‹ˆλ‹€(μ†ŒμΌ“μ΄ μ—°κ²° λ˜λŠ” μž¬μ—°κ²°λ  λ•Œ μ‹€ν–‰λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€, afaik?).

ν˜„μž¬ μ„œλ²„ 인증이 μž¬μ—°κ²°μ— μ‹€νŒ¨ν•˜κ³  토큰이 λ§Œλ£Œλ˜μ—ˆλ‹€κ³  ν•©λ‹ˆλ‹€. μƒˆ 토큰이 socket.io.opts.query.token 에 μ œλŒ€λ‘œ ν• λ‹Ήλ˜μ§€ μ•Šμ€ 것 κ°™μŠ΅λ‹ˆλ‹€. μ΄μœ κ°€ λ¬΄μ—‡μž…λ‹ˆκΉŒ?

감사 ν•΄μš” :)

μ—…λ°μ΄νŠΈ: μ†ŒμΌ“ κ°œμ²΄μ— 인증 토큰이 μ €μž₯된 μ—¬λŸ¬ μœ„μΉ˜κ°€ μžˆλŠ” 것 κ°™μŠ΅λ‹ˆλ‹€(예: socket.io.engine.query.token , socket.io.engine.transport.query.token . socket.io.opts.query.token λ₯Ό μ„€μ •ν•  λ•Œ μžλ™μœΌλ‘œ μ±„μ›Œμ§€μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 이것을 변경해도 μ„œλ²„κ°€ 'λ³΄λŠ”' λ‚΄μš©μ—λŠ” 영ν–₯을 λ―ΈμΉ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μ—¬μ „νžˆ 이전 ν† ν°λ§Œ λ΄…λ‹ˆλ‹€.

토큰은 λ˜ν•œ μ†ŒμΌ“ 개체의 일뢀 url ν•„λ“œμ— URL λ§€κ°œλ³€μˆ˜λ‘œ ν¬ν•¨λœ κ²ƒμœΌλ‘œ λ³΄μž…λ‹ˆλ‹€. μ•„λ§ˆλ„ 이것듀도 μ—…λ°μ΄νŠΈλ˜μ–΄μ•Ό ν•©λ‹ˆκΉŒ?

더 μ‘°μ‚¬ν•œ κ²°κ³Ό 토큰을 socket.io.opts.query.token 둜 μ„€μ •ν•˜λ©΄ λ‹€μ‹œ μ—°κ²°ν•  λ•Œ μž¬μΈμ¦μ„ μœ„ν•΄ 토큰을 λ³€κ²½ν•˜λŠ” 데 μΆ©λΆ„ν•œ κ²ƒμœΌλ‘œ λ³΄μž…λ‹ˆλ‹€. λ‚΄ 앱에 λ‹€λ₯Έ λ¬Έμ œκ°€ μžˆλŠ” 것 κ°™μŠ΅λ‹ˆλ‹€. Firebase 인증 토큰 생성과 관련이 μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ 이것을 μ ‘ν•˜λŠ” λ‹€λ₯Έ μ‚¬λžŒμ—κ²ŒλŠ”

μ’‹μ•„, λ‚΄κ°€ 그것을 κ³ μ³€λ‹€κ³  μƒκ°ν•œλ‹€ - 당신은 'reconnect_attempt' μ½œλ°±μ—μ„œ 동기적 으둜 μƒˆ 토큰을 λ°›κ³  μžˆλŠ”μ§€ 확인해야 ν•œλ‹€. 즉, λ‹€μŒκ³Ό 같이 ν•˜μ§€ 말라.

 socket.on('reconnect_attempt', async () => {
      const newToken = await getNewToken(); // won't work
      socket.io.opts.query = {
        token: latestToken,
      };
    });

μƒˆ 토큰이 μ„€μ •λ˜κΈ° 전에 μ„œλ²„ μΈ‘ 인증이 μ™„λ£Œλœ 것 κ°™μŠ΅λ‹ˆλ‹€. 토큰을 λ™κΈ°μ‹μœΌλ‘œ κ°€μ Έμ˜€λ©΄(이전에 일정 μ‹œκ°„ λ™μ•ˆ 가져와 μ €μž₯ν•œ λ‹€μŒ μˆ˜μ‹ κΈ° μ½œλ°±μ—μ„œ κ²€μƒ‰ν•˜μ—¬) μ„œλ²„λŠ” μž¬μ—°κ²° 인증을 μœ„ν•œ μ‹œκ°„μ— μƒˆ 인증 토큰을 κ°€μ Έμ˜΅λ‹ˆλ‹€.

"socket.io-client": "3.0.4" 와 ν•¨κ»˜ TS2341: Property 'opts' is private and only accessible within class 'Manager'. 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€. "typescript": "4.1.3"
image

μ’‹μ•„, λ‚΄κ°€ 그것을 κ³ μ³€λ‹€κ³  μƒκ°ν•œλ‹€ - 당신은 당신이 'reconnect_attempt' μ½œλ°±μ—μ„œ _λ™κΈ°μ μœΌλ‘œ_ μƒˆλ‘œμš΄ 토큰을 λ°›κ³  μžˆλŠ”μ§€ 확인해야 ν•œλ‹€. 즉, 이것을 ν•˜μ§€ 말라:

 socket.on('reconnect_attempt', async () => {
      const newToken = await getNewToken(); // won't work
      socket.io.opts.query = {
        token: latestToken,
      };
    });

μƒˆ 토큰이 μ„€μ •λ˜κΈ° 전에 μ„œλ²„ μΈ‘ 인증이 μ™„λ£Œλœ 것 κ°™μŠ΅λ‹ˆλ‹€. 토큰을 λ™κΈ°μ‹μœΌλ‘œ κ°€μ Έμ˜€λ©΄(이전에 일정 μ‹œκ°„ λ™μ•ˆ 가져와 μ €μž₯ν•œ λ‹€μŒ μˆ˜μ‹ κΈ° μ½œλ°±μ—μ„œ κ²€μƒ‰ν•˜μ—¬) μ„œλ²„λŠ” μž¬μ—°κ²° 인증을 μœ„ν•œ μ‹œκ°„μ— μƒˆ 인증 토큰을 κ°€μ Έμ˜΅λ‹ˆλ‹€.

λΉ„μŠ·ν•œ λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ ν˜„μž¬ ν•΄κ²° 방법은 인증이 μ‹€νŒ¨ν•  λ•Œ μ„œλ²„ μΈ‘μ—μ„œ disconnect μž…λ‹ˆλ‹€. ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ disconnect 이벀트λ₯Ό μˆ˜μ‹ ν•˜λ©΄ 비동기 약속 호좜둜 쿼리/헀더λ₯Ό μž¬κ΅¬μ„±ν•©λ‹ˆλ‹€. reconnecting μ΄λ²€νŠΈμ— λ„λ‹¬ν–ˆμ„ λ•Œ 이미 쿼리/헀더에 μƒˆ 값이 μžˆμŠ΅λ‹ˆλ‹€.

미래의 λ…μžλ₯Ό μœ„ν•΄:

Socket.IO v2μ—μ„œ query μ˜΅μ…˜μ˜ λ™μž‘μ€ λ‹€μŒ 두 가지 λͺ¨λ‘μ—μ„œ μ‚¬μš©λ˜κΈ° λ•Œλ¬Έμ— μ•½κ°„ μ΄μƒν•©λ‹ˆλ‹€.

  • 쿼리 λ§€κ°œλ³€μˆ˜(Manager μΈμŠ€ν„΄μŠ€μš©)
  • Socket.IO ν•Έλ“œμ…°μ΄ν¬(기본이 μ•„λ‹Œ λ„€μž„μŠ€νŽ˜μ΄μŠ€μ—λ§Œ ν•΄λ‹Ή)

κ·Έλž˜μ„œ 이전 버전과 ν˜Έν™˜λ˜λŠ” λ°©μ‹μœΌλ‘œ μ–΄λ–»κ²Œ κ³ μΉ  수 μžˆλŠ”μ§€ 잘 λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€...

이제 auth μ˜΅μ…˜μ„ μ‚¬μš©ν•  수 μžˆμœΌλ―€λ‘œ Socket.IO v3μ—μ„œ μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

// plain object
const socket = io({
  auth: {
    token: "abc"
  }
});

// or with a function
const socket = io({
  auth: (cb) => {
    cb({
      token: "abc"
    });
  }
});

async ν•¨μˆ˜μ—μ„œλ„ μž‘λ™ν•΄μ•Ό ν•©λ‹ˆλ‹€.

const socket = io({
  auth: async (cb) => {
    cb({
      token: "abc"
    });
  }
});

λ˜ν•œλ³΄μ‹­μ‹œμ˜€:

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰