use of org.kin.rsocket.auth.RSocketAppPrincipal in project kin-rsocket-broker by huangjianqin.
the class RSocketServiceManager method acceptor.
/**
* service rsocket endpoint acceptor逻辑
*/
@SuppressWarnings("ConstantConditions")
@Nonnull
private Mono<RSocket> acceptor(ConnectionSetupPayload setupPayload, RSocket requester) {
// parse setup payload
RSocketCompositeMetadata compositeMetadata = null;
AppMetadata appMetadata = null;
String credentials = "";
RSocketAppPrincipal principal = null;
String errorMsg = null;
try {
compositeMetadata = RSocketCompositeMetadata.of(setupPayload.metadata());
if (!authRequired) {
// authentication not required
principal = RSocketAppPrincipal.DEFAULT;
credentials = UUID.randomUUID().toString();
} else if (compositeMetadata.contains(RSocketMimeType.BEARER_TOKEN)) {
BearerTokenMetadata bearerTokenMetadata = compositeMetadata.getMetadata(RSocketMimeType.BEARER_TOKEN);
credentials = new String(bearerTokenMetadata.getBearerToken());
principal = authenticationService.auth(credentials);
} else {
// no jwt token supplied
errorMsg = "Failed to accept the connection, please check app info and JWT token";
}
// validate application information
if (principal != null && compositeMetadata.contains(RSocketMimeType.APPLICATION)) {
AppMetadata temp = compositeMetadata.getMetadata(RSocketMimeType.APPLICATION);
// App registration validation: app id: UUID and unique in server
String appId = temp.getUuid();
// validate appId data format
if (StringUtils.isNotBlank(appId) && appId.length() >= 32) {
int instanceId = MurmurHash3.hash32(credentials + ":" + temp.getUuid());
temp.updateInstanceId(instanceId);
// application instance not connected
if (!containsInstanceId(instanceId)) {
appMetadata = temp;
appMetadata.updateConnectedAt(new Date());
} else {
// application connected already
errorMsg = "Connection created already, Please don't create multiple connections.";
}
} else {
// 没有uuid是否要拒绝连接
// illegal application id, appID should be UUID
errorMsg = String.format("'%s' is not legal application ID, please supply legal UUID as Application ID", appId == null ? "" : appId);
}
} else {
errorMsg = "Can not found application metadata";
}
if (errorMsg == null) {
// Security authentication
if (appMetadata != null) {
appMetadata.addMetadata("_orgs", String.join(",", principal.getOrganizations()));
appMetadata.addMetadata("_roles", String.join(",", principal.getRoles()));
appMetadata.addMetadata("_serviceAccounts", String.join(",", principal.getServiceAccounts()));
} else {
errorMsg = "Please supply message/x.rsocket.application+json metadata in setup payload";
}
}
} catch (Exception e) {
log.error("Error to parse setup payload", e);
errorMsg = String.format("Failed to parse composite metadata: %s", e.getMessage());
}
// validate connection legal or not
if (principal == null) {
errorMsg = "Failed to accept the connection, please check app info and JWT token";
}
if (errorMsg != null) {
return returnRejectedRSocket(errorMsg, requester);
}
// create rsocket endpoint
try {
RSocketBrokerResponderHandler responderHandler = new RSocketBrokerResponderHandler(setupPayload, appMetadata, principal, this, serviceMeshInspector, upstreamBrokers, rsocketFilterChain);
RSocketEndpoint rsocketEndpoint = new RSocketEndpoint(compositeMetadata, appMetadata, requester, this, responderHandler);
rsocketEndpoint.onClose().doOnTerminate(() -> onRSocketEndpointDisposed(rsocketEndpoint)).subscribeOn(Schedulers.parallel()).subscribe();
// handler registration notify
registerRSocketEndpoint(rsocketEndpoint);
// connect success, so publish service now
rsocketEndpoint.publishServices();
log.info(String.format("succeed to accept connection from application '%s'", appMetadata.getName()));
return Mono.just(responderHandler);
} catch (Exception e) {
String formattedErrorMsg = String.format("failed to accept the connection: %s", e.getMessage());
log.error(formattedErrorMsg, e);
return returnRejectedRSocket(formattedErrorMsg, requester);
}
}
use of org.kin.rsocket.auth.RSocketAppPrincipal in project kin-rsocket-broker by huangjianqin.
the class RSocketApiController method handle.
@RequestMapping(value = "/{service}/{method}", produces = { MediaType.APPLICATION_JSON_VALUE })
public Mono<ResponseEntity<String>> handle(@PathVariable("service") String service, @PathVariable("method") String method, @RequestParam(name = "group", required = false, defaultValue = "") String group, @RequestParam(name = "version", required = false, defaultValue = "") String version, @RequestBody(required = false) byte[] body, @RequestHeader(name = "X-Endpoint", required = false, defaultValue = "") String endpoint, @RequestHeader(name = HttpHeaders.AUTHORIZATION, required = false, defaultValue = "") String token) {
try {
GSVRoutingMetadata routingMetadata = GSVRoutingMetadata.of(group, service, method, version);
int serviceId = routingMetadata.serviceId();
ByteBuf bodyBuf = body == null ? EMPTY_BUFFER : Unpooled.wrappedBuffer(body);
RSocketEndpoint rsocketEndpoint;
if (endpoint.startsWith("id:")) {
// 存在endpoint
int instanceId = Integer.parseInt(endpoint.substring(3).trim());
rsocketEndpoint = serviceManager.getByInstanceId(instanceId);
} else {
rsocketEndpoint = serviceManager.routeByServiceId(serviceId);
}
if (Objects.nonNull(rsocketEndpoint)) {
if (rsocketBrokerProperties.isAuth()) {
RSocketAppPrincipal principal = authenticationService.auth(token);
if (principal == null || !serviceMeshInspector.isAllowed(principal, serviceId, rsocketEndpoint.getPrincipal())) {
return Mono.just(error(String.format("Service request not allowed '%s'", routingMetadata.gsv())));
}
}
RSocketCompositeMetadata compositeMetadata = RSocketCompositeMetadata.of(routingMetadata, JSON_ENCODING_METADATA);
return rsocketEndpoint.requestResponse(DefaultPayload.create(bodyBuf, compositeMetadata.getContent())).map(payload -> {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setCacheControl(CacheControl.noCache().getHeaderValue());
return new ResponseEntity<>(payload.getDataUtf8(), headers, HttpStatus.OK);
});
}
return Mono.just(error(String.format("service not found, '%s'", routingMetadata.gsv())));
} catch (Exception e) {
return Mono.just(error(e.getMessage()));
}
}
use of org.kin.rsocket.auth.RSocketAppPrincipal in project kin-rsocket-broker by huangjianqin.
the class JwtAuthenticationService method auth.
@Override
public RSocketAppPrincipal auth(String credentials) {
if (Objects.isNull(credentials) || credentials.isEmpty()) {
return null;
}
// bearer jwt_token
credentials = credentials.substring(credentials.lastIndexOf(" ") + 1);
int tokenHashCode = credentials.hashCode();
RSocketAppPrincipal principal = jwtVerifyCache.getIfPresent(tokenHashCode);
for (JWTVerifier verifier : verifiers) {
try {
principal = new JwtPrincipal(verifier.verify(credentials));
jwtVerifyCache.put(tokenHashCode, principal);
break;
} catch (JWTVerificationException ignore) {
// do nothing
}
}
return principal;
}
Aggregations