django channels custom token authenticated Websocket keeps disconnecting ERR_CONNECTION_RESET

我的未来我决定 提交于 2020-05-17 07:27:31

问题


i using react as my front end and django as my backend , as such , it requires me to use token based authentication with django channels. The method i am employing is by sending the authentication token as a cookie header. The methodology was taken from this git hub post here

So far , i have gotten most of the working parts together , however i don't seem to be able to persist the connection , it will always return an error in my console:

 ERR_CONNECTION_RESET

Here is my code:

FRONTEND: 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;

FRONTEND: 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 ( A custom middleware)

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

Here is my the items that were printed out in my cmd prompt:

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

Please help! Im lost!


回答1:


the issue was with the middleware instance , it should be :

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

thanks!



来源:https://stackoverflow.com/questions/61413375/django-channels-custom-token-authenticated-websocket-keeps-disconnecting-err-con

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!