django通道经过身份验证的自定义令牌Websocket不断断开ERR_CONNECTION_RESET

问题描述 投票:0回答:1

我使用react作为我的前端,使用django作为我的后端,因此,它要求我对django通道使用基于令牌的身份验证。我采用的方法是通过发送身份验证令牌作为cookie头。该方法学取自此git hub帖子here

到目前为止,我已经将大多数工作部件放在一起,但是我似乎无法持久连接,它将始终在我的控制台中返回错误:

 ERR_CONNECTION_RESET

这是我的代码:

前:Websocket.js

class WebSocketService{
static instance = null; 
callbacks = {};

static getInstance(){
    if (!WebSocketService.instance){
        WebSocketService.instance = new WebSocketService();
    }
    return WebSocketService.instance;
}

constructor(){
    this.socketRef = null;
}

connect(token){
    var loc = window.location
    var wsStart = 'ws://'
    if (loc.protocol === 'https'){
      wsStart = 'wss://'
    }
    const path = wsStart + 'localhost:8000'+ loc.pathname
    // console.log(path)
    // console.log(path + "?token=" + token)
    document.cookie = 'authorization=' + token + ';' 
    console.log(document.cookie)
    this.socketRef = new WebSocket(path)

    this.socketRef.onmessage = e => {
        console.log('in on message')
        this.socketNewMessage(e.data);
      };

    this.socketRef.onopen = () => {
        console.log(this.props.token)
        console.log("WebSocket open");
    };

    this.socketRef.onerror = e => {
        console.log('error happ')
        console.log(e.message);
    };

    this.socketRef.onclose = () => {
        console.log("WebSocket closed, restarting..");
        this.connect(token);
    };   
}

socketNewMessage(data){
    const parsedData = JSON.parse(data);
    const command = parsedData.command;
    if(Object.keys(this.callbacks).length === 0){
        return;
    }
    if(command === 'messages'){
        this.callbacks[command](parsedData.messages);
    }
    if(command === 'new_message'){
        console.log("okay so this was called")
        this.callbacks[command](parsedData.message);
    }
}

state(){
    return this.socketRef.readyState;
}
waitForSocketConnection(callback){
    const socket = this.socketRef;
    const recursion = this.waitForSocketConnection;
    setTimeout(
        function(){
            if(socket.readyState === 1){
                console.log("Connection is made");
                if(callback != null){
                    callback();
                }
                return;
            }
            else{
                console.log("Wait for connection..");
                recursion(callback);
            }
        }, 1);
}
}

    let WebSocketInstance = WebSocketService.getInstance();

    export default WebSocketInstance;

前:Apps.js

class App extends Component {

  componentDidMount() {
    console.log('app mounting..')
    this.props.onTryAutoSignup();
    console.log(this.props.isAuthenticated)
    if (this.props.isAuthenticated) {
      WebSocketInstance.connect()    
    }
  }

  componentDidUpdate(oldProps) {
    console.log('app updating props..')
    if (this.props.token !== oldProps.token ) {
      console.log(this.props.token)
      WebSocketInstance.connect(this.props.token)       
    }
  }

  render() {
    return (
      <div>
        <Router>
          <CustomLayout {...this.props}>
                <BaseRouter/>
          </CustomLayout>
        </Router>
      </div>
    );
  }
}

const mapStateToProps = state => {
  return {
    isAuthenticated: state.token !== null ,
    token : state.token
  }
}

const mapDispatchToProps = dispatch => {
  return {
    onTryAutoSignup: () => dispatch(actions.authCheckState())
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(App);

BACKEND:token_auth.py(自定义中间件)

@database_sync_to_async
def get_user(token_key):
    try:
        return Token.objects.get(key=token_key).user
    except Token.DoesNotExist:
        return AnonymousUser()


class TokenAuthMiddleware:
    """
    Token authorization middleware for Django Channels 2
    see:
    https://channels.readthedocs.io/en/latest/topics/authentication.html#custom-authentication
    """

    def __init__(self, inner):
        self.inner = inner

    def __call__(self, scope):
        return TokenAuthMiddlewareInstance(scope, self)


class TokenAuthMiddlewareInstance:
    def __init__(self, scope, middleware):
        self.middleware = middleware
        self.scope = dict(scope)
        self.inner = self.middleware.inner

    async def __call__(self, receive, send):
        headers = dict(self.scope["headers"])
        print(headers[b"cookie"])
        if b"authorization" in headers[b"cookie"]:
            print('still good here')
            cookies = headers[b"cookie"].decode()
            token_key = re.search("authorization=(.*)(; )?", cookies).group(1)
            if token_key:
                self.scope["user"] = await get_user(token_key)

        return self.inner(self.scope)

BACKEND:Router.py

    application = ProtocolTypeRouter({
    "websocket": TokenAuthMiddlewareStack(
        URLRouter([
            path("", NotificationConsumer),
        ]),
    ),

})

TokenAuthMiddlewareStack = lambda inner: TokenAuthMiddleware(AuthMiddlewareStack(inner))

这是我在cmd提示符下打印出的项目:

WebSocket HANDSHAKING / [127.0.0.1:59931]
b'authorization=xxxxxxxxxxxx' #<-- token from the cookie header
still good here #<--- passed first validation
user1  #<---- went into the get_user function i declared within my middleware
WebSocket DISCONNECT / [127.0.0.1:59931]   #<---- disconnects...

请帮助!我迷路了!

javascript django reactjs websocket django-channels
1个回答
0
投票

问题出在中间件实例上,应该是:

class TokenAuthMiddlewareInstance:
    def __init__(self, scope, middleware):
        self.middleware = middleware
        self.scope = dict(scope)
        self.inner = self.middleware.inner

    async def __call__(self, receive, send):
        close_old_connections()
        headers = dict(self.scope["headers"])
        print(headers[b"cookie"])
        if b"authorization" in headers[b"cookie"]:
            print('still good here')
            cookies = headers[b"cookie"].decode()
            token_key = re.search("authorization=(.*)(; )?", cookies).group(1)
            if token_key:
                self.scope["user"] = await get_user(token_key)

        inner = self.inner(self.scope)
        return await inner(receive, send) 


TokenAuthMiddlewareStack = lambda inner: TokenAuthMiddleware(AuthMiddlewareStack(inner))

谢谢!

© www.soinside.com 2019 - 2024. All rights reserved.