Browse Source

authroziation listener. Issue #48

master
Nikita 12 years ago
parent
commit
e4eda5e33f
  1. 13
      src/main/java/com/corundumstudio/socketio/AuthorizationListener.java
  2. 20
      src/main/java/com/corundumstudio/socketio/Configuration.java
  3. 50
      src/main/java/com/corundumstudio/socketio/HandshakeData.java
  4. 44
      src/main/java/com/corundumstudio/socketio/handler/AuthorizeHandler.java
  5. 13
      src/main/java/com/corundumstudio/socketio/handler/SuccessAuthorizationListener.java

13
src/main/java/com/corundumstudio/socketio/AuthorizationListener.java

@ -0,0 +1,13 @@
package com.corundumstudio.socketio;
public interface AuthorizationListener {
/**
* Checks is client with handshake data is authorized
*
* @param data - handshake data
* @return - <b>true</b> if client is authorized of <b>false</b> otherwise
*/
boolean isAuthorized(HandshakeData data);
}

20
src/main/java/com/corundumstudio/socketio/Configuration.java

@ -19,6 +19,7 @@ import io.netty.handler.codec.TooLongFrameException;
import java.io.InputStream;
import com.corundumstudio.socketio.handler.SuccessAuthorizationListener;
import com.corundumstudio.socketio.parser.JacksonJsonSupport;
import com.corundumstudio.socketio.parser.JsonSupport;
import com.corundumstudio.socketio.store.MemoryStoreFactory;
@ -58,6 +59,8 @@ public class Configuration {
private JsonSupport jsonSupport = new JacksonJsonSupport(this);
private AuthorizationListener authorizationListener = new SuccessAuthorizationListener();
public Configuration() {
}
@ -94,6 +97,7 @@ public class Configuration {
setPreferDirectBuffer(conf.isPreferDirectBuffer());
setStoreFactory(conf.getStoreFactory());
setAuthorizationListener(conf.getAuthorizationListener());
}
private String join(Transport[] transports) {
@ -363,5 +367,21 @@ public class Configuration {
return storeFactory;
}
/**
* Authorization listener invoked on every handshake.
* Accepts or denies a client by {@code AuthorizationListener.isAuthorized} method.
* <b>Accepts</b> all clients by default.
*
* @param authorizationListener - authorization listener itself
*
* @see com.corundumstudio.socketio.AuthorizationListener
*/
public void setAuthorizationListener(AuthorizationListener authorizationListener) {
this.authorizationListener = authorizationListener;
}
public AuthorizationListener getAuthorizationListener() {
return authorizationListener;
}
}

50
src/main/java/com/corundumstudio/socketio/HandshakeData.java

@ -0,0 +1,50 @@
package com.corundumstudio.socketio;
import java.net.InetSocketAddress;
import java.util.Date;
import java.util.List;
import java.util.Map;
public final class HandshakeData {
private final Map<String, List<String>> headers;
private final InetSocketAddress address;
private final Date time = new Date();
private final String url;
private final Map<String, List<String>> urlParams;
private final boolean xdomain;
public HandshakeData(Map<String, List<String>> headers, Map<String, List<String>> urlParams, InetSocketAddress address, String url, boolean xdomain) {
super();
this.headers = headers;
this.urlParams = urlParams;
this.address = address;
this.url = url;
this.xdomain = xdomain;
}
public InetSocketAddress getAddress() {
return address;
}
public Map<String, List<String>> getHeaders() {
return headers;
}
public Date getTime() {
return time;
}
public String getUrl() {
return url;
}
public boolean isXdomain() {
return xdomain;
}
public Map<String, List<String>> getUrlParams() {
return urlParams;
}
}

44
src/main/java/com/corundumstudio/socketio/handler/AuthorizeHandler.java

@ -30,6 +30,8 @@ import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.QueryStringDecoder;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -41,6 +43,7 @@ import org.slf4j.LoggerFactory;
import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.Disconnectable;
import com.corundumstudio.socketio.HandshakeData;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.messages.AuthorizeMessage;
import com.corundumstudio.socketio.misc.ConcurrentHashSet;
@ -90,7 +93,7 @@ public class AuthorizeHandler extends ChannelInboundHandlerAdapter implements Di
}
if (queryDecoder.path().equals(connectPath)) {
String origin = req.headers().get(HttpHeaders.Names.ORIGIN);
authorize(channel, origin, queryDecoder.parameters());
authorize(channel, origin, queryDecoder.parameters(), req);
req.release();
return;
}
@ -98,9 +101,9 @@ public class AuthorizeHandler extends ChannelInboundHandlerAdapter implements Di
ctx.fireChannelRead(msg);
}
private void authorize(Channel channel, String origin, Map<String, List<String>> params)
private void authorize(Channel channel, String origin, Map<String, List<String>> params, FullHttpRequest req)
throws IOException {
final UUID sessionId = UUID.randomUUID();
UUID sessionId = UUID.randomUUID();
authorizedSessionIds.add(sessionId);
scheduleDisconnect(channel, sessionId);
@ -110,16 +113,35 @@ public class AuthorizeHandler extends ChannelInboundHandlerAdapter implements Di
heartbeatTimeoutVal = "";
}
String msg = sessionId + ":" + heartbeatTimeoutVal + ":" + configuration.getCloseTimeout() + ":" + configuration.getTransports();
List<String> jsonpParams = params.get("jsonp");
String jsonpParam = null;
if (jsonpParams != null) {
jsonpParam = jsonpParams.get(0);
Map<String, List<String>> headers = new HashMap<String, List<String>>();
for (String name : req.headers().names()) {
List<String> values = req.headers().getAll(name);
headers.put(name, values);
}
channel.write(new AuthorizeMessage(msg, jsonpParam, origin, sessionId));
log.debug("New sessionId: {} authorized", sessionId);
HandshakeData data = new HandshakeData(headers, params,
(InetSocketAddress)channel.remoteAddress(),
req.getUri(), origin != null && !origin.equalsIgnoreCase("null"));
boolean result = configuration.getAuthorizationListener().isAuthorized(data);
if (result) {
String msg = sessionId + ":" + heartbeatTimeoutVal + ":" + configuration.getCloseTimeout() + ":" + configuration.getTransports();
List<String> jsonpParams = params.get("jsonp");
String jsonpParam = null;
if (jsonpParams != null) {
jsonpParam = jsonpParams.get(0);
}
channel.write(new AuthorizeMessage(msg, jsonpParam, origin, sessionId));
log.debug("Handshake authorized for sessionId: {}", sessionId);
} else {
HttpResponse res = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.FORBIDDEN);
ChannelFuture f = channel.write(res);
f.addListener(ChannelFutureListener.CLOSE);
log.debug("Handshake unauthorized");
}
}
private void scheduleDisconnect(Channel channel, final UUID sessionId) {

13
src/main/java/com/corundumstudio/socketio/handler/SuccessAuthorizationListener.java

@ -0,0 +1,13 @@
package com.corundumstudio.socketio.handler;
import com.corundumstudio.socketio.AuthorizationListener;
import com.corundumstudio.socketio.HandshakeData;
public class SuccessAuthorizationListener implements AuthorizationListener {
@Override
public boolean isAuthorized(HandshakeData data) {
return true;
}
}
Loading…
Cancel
Save