so i managed to solve this issue!
The problem was on the server side. all i did was update the AsyncSocketServlet class with the following code
/*
* Copyright 2015 - 2016 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.traccar.api;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
import org.eclipse.jetty.websocket.servlet.WebSocketCreator;
import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
import org.traccar.Context;
import org.traccar.api.resource.SessionResource;
import org.traccar.helper.Log;
import org.traccar.model.User;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import java.lang.reflect.Method;
import java.sql.SQLException;
public class AsyncSocketServlet extends WebSocketServlet {
public static final String AUTHORIZATION_HEADER = "Authorization";
public static final String WWW_AUTHENTICATE = "WWW-Authenticate";
public static final String BASIC_REALM = "Basic realm=\"api\"";
public static final String X_REQUESTED_WITH = "X-Requested-With";
public static final String XML_HTTP_REQUEST = "XMLHttpRequest";
private static final long ASYNC_TIMEOUT = 10 * 60 * 1000;
@javax.ws.rs.core.Context
private HttpServletRequest request;
@javax.ws.rs.core.Context
private ResourceInfo resourceInfo;
@javax.ws.rs.core.Context
private SecurityContext securityContext;
protected long getUserId() {
UserPrincipal principal = (UserPrincipal) securityContext.getUserPrincipal();
if (principal != null) {
return principal.getUserId();
}
return 0;
}
@Override
public void configure(WebSocketServletFactory factory) {
factory.getPolicy().setIdleTimeout(Context.getConfig().getLong("web.timeout", ASYNC_TIMEOUT));
factory.setCreator(new WebSocketCreator() {
@Override
public Object createWebSocket(ServletUpgradeRequest req, ServletUpgradeResponse resp) {
auth(req);
return new AsyncSocket(getUserId());
}
});
}
private void auth(ServletUpgradeRequest req) {
request = req.getHttpServletRequest();
if (req.getHttpServletRequest().getMethod().equals("OPTIONS")) {
return;
}
SecurityContext securityContext = null;
try {
String authHeader = request.getHeader(AUTHORIZATION_HEADER);
if (authHeader != null) {
try {
String[] auth = SecurityRequestFilter.decodeBasicAuth(authHeader);
User user = Context.getPermissionsManager().login(auth[0], auth[1]);
if (user != null) {
Context.getStatisticsManager().registerRequest(user.getId());
securityContext = new UserSecurityContext(new UserPrincipal(user.getId()));
}
} catch (SQLException e) {
throw new WebApplicationException(e);
}
} else if (req.getSession() != null) {
Long userId = (Long) req.getSession().getAttribute(SessionResource.USER_ID_KEY);
if (userId != null) {
Context.getPermissionsManager().checkUserEnabled(userId);
Context.getStatisticsManager().registerRequest(userId);
securityContext = new UserSecurityContext(new UserPrincipal(userId));
}
}
} catch (SecurityException e) {
Log.warning(e);
}
if (securityContext != null) {
this.securityContext = securityContext;
} else {
Method method = resourceInfo.getResourceMethod();
if (!method.isAnnotationPresent(PermitAll.class)) {
Response.ResponseBuilder responseBuilder = Response.status(Response.Status.UNAUTHORIZED);
if (!XML_HTTP_REQUEST.equals(request.getHeader(X_REQUESTED_WITH))) {
responseBuilder.header(WWW_AUTHENTICATE, BASIC_REALM);
}
throw new WebApplicationException(responseBuilder.build());
}
}
}
}
the same code can be found here (https://github.com/traccar/traccar/blob/dcbace81a786e6b9157937c10eebed441a03dcfa/src/org/traccar/api/AsyncSocketServlet.java)
i hope this helps anyone facing the same issue
Hello, is it possible to contact you for asking you some questions about traccar and websocket? thank you
My email [redacted]
i've created a java websocket client using javax.websocket:javax.websocket-client-api:1.0 library.
iv attempted to establish a websocket connection to the traccar server but i keep getting the following error :
iv gone through numerous sources (one of which being this one (https://www.traccar.org/forums/topic/python-websockets-results-in-handshake-status-503/)) and it has come to my understanding that i should use cookie session authentication. However im not sure how to do so.
My current Endpoint implementation is the following
package ocsy.app.config; import javax.websocket.*; import java.net.URI; import java.util.Arrays; import java.util.Map; import java.util.logging.Logger; import static ocsy.app.utils.Utils.auth; @ClientEndpoint public class WebsocketClientEndpoint extends Endpoint { private Logger logger = Logger.getLogger(this.getClass().getName()); Session session = null; public WebsocketClientEndpoint(String endpointURI) { //start connection javax.websocket.WebSocketContainer container = javax.websocket.ContainerProvider.getWebSocketContainer(); try { ClientEndpointConfig.Configurator configurator = new ClientEndpointConfig.Configurator() { public void beforeRequest(Map headers) { headers.put("Authorization", Arrays.asList(auth("admin","admin"))); } }; ClientEndpointConfig clientConfig = ClientEndpointConfig.Builder.create() .configurator(configurator) .build(); container.connectToServer(this,clientConfig, new URI(endpointURI)); } catch (Exception e) { e.printStackTrace(); } } @Override public void onOpen(Session session,EndpointConfig config) { logger.info("Client onOpen..." + session.getId()); this.session = session; } @OnMessage public void onMessage(String message, Session session) { logger.info("MyClientEndpoint log: " + message); } @Override public void onClose(Session session, CloseReason closeReason) { logger.info(String.format("Session %s close because of %s", session.getId(), closeReason)); } }
I instatiated the method as follows :
WebsocketClientEndpoint clientEndPoint = new WebsocketClientEndpoint("ws://ocsytracker.hopto.org:8082/api/socket");
I get the following error :
I'd very much appreciate anyones help on the matter. Thank you in advance