Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@

package org.apache.storm.security.auth;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.net.InetAddress;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Principal;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
Expand All @@ -36,19 +37,22 @@
* </ol>
*/
public class ReqContext {

private static final MethodHandle CURRENT = lookupCurrent();

private static final AtomicInteger uniqueId = new AtomicInteger(0);
//each thread will have its own request context
private static final ThreadLocal<ReqContext> ctxt =
ThreadLocal.withInitial(() -> new ReqContext(AccessController.getContext()));
ThreadLocal.withInitial(ReqContext::new);
private Subject subject;
private InetAddress remoteAddr;
private final int reqId;
private Principal realPrincipal;

//private constructor
@VisibleForTesting
public ReqContext(AccessControlContext aclCtxt) {
subject = Subject.getSubject(aclCtxt);
public ReqContext() {
subject = currentSubject();
reqId = uniqueId.incrementAndGet();
}

Expand Down Expand Up @@ -161,4 +165,66 @@ public boolean isImpersonating() {
public int requestID() {
return reqId;
}

/**
* Maps to Subject.current() is available, otherwise maps to Subject.getSubject()
* @return the current subject
*/
public static Subject currentSubject() {
try {
return (Subject) CURRENT.invoke();
} catch (Throwable t) {
throw new RuntimeException(t);
}
}

private static MethodHandle lookupCurrent() {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
try {
// Subject.getSubject(AccessControlContext) is deprecated for removal and replaced by
// Subject.current().
// Lookup first the new API, since for Java versions where both exists, the
// new API delegates to the old API (for example Java 18, 19 and 20).
// Otherwise (Java 17), lookup the old API.
return lookup.findStatic(Subject.class, "current",
MethodType.methodType(Subject.class));
} catch (NoSuchMethodException e) {
final MethodHandle getContext = lookupGetContext();
final MethodHandle getSubject = lookupGetSubject();
return MethodHandles.filterReturnValue(getContext, getSubject);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
}

private static MethodHandle lookupGetSubject() {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
try {
final Class<?> contextClazz =
ClassLoader.getSystemClassLoader()
.loadClass("java.security.AccessControlContext");
return lookup.findStatic(Subject.class, "getSubject",
MethodType.methodType(Subject.class, contextClazz));
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException e) {
throw new AssertionError(e);
}
}

private static MethodHandle lookupGetContext() {
try {
// Use reflection to work with Java versions that have and don't have AccessController.
final Class<?> controllerClazz =
ClassLoader.getSystemClassLoader().loadClass("java.security.AccessController");
final Class<?> contextClazz =
ClassLoader.getSystemClassLoader()
.loadClass("java.security.AccessControlContext");

MethodHandles.Lookup lookup = MethodHandles.lookup();
return lookup.findStatic(controllerClazz, "getContext",
MethodType.methodType(contextClazz));
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException e) {
throw new AssertionError(e);
}
}

}