이 질문은 높은 수준에서 my previous question about unusual exceptions generated by a custom security manager.의 후속, 내가 신뢰할 수없는 코드와 함께 신뢰할 수있는 코드를 실행하는 응용 프로그램을 구축에 관심이 있어요. 나의 초기 아이디어는 대부분의 작업이 실행되지 않도록하는 사용자 정의 SecurityManager
을 작성하는 것이 었습니다. 이로 인해 신뢰할 수없는 객체를 인스턴스화하는 신뢰할 수있는 반사 코드가 16 번의 호출 후에 실패한 비정상적인 동작이 발생했습니다.왜 이처럼 겉으로는 동등한 SecurityManager 코드가 잘못된 예외를 유발합니까?
코드를 다시 작성하여 SecurityManager
사용자 지정을 사용하는 대신 신뢰할 수없는 코드가 실행되는 새로운 보호 도메인을 만들고 해당 신뢰할 수없는 코드에서 사용 권한을 제거합니다. 이 새로운 코드는 여기에 표시됩니다 :
import java.io.FilePermission;
import java.lang.reflect.*;
import java.security.*;
public class Main {
/* Track how many instances have been created so that we can see when the exception
* is thrown.
*/
private static int numInstances = 0;
public Main() {
System.out.println("Number created: " + ++numInstances);
}
/* Utility function that returns a Constructor object for main. */
private static Constructor<Main> getCtor() {
try {
return Main.class.getConstructor();
} catch (NoSuchMethodException e) {
e.printStackTrace();
System.exit(-1);
return null; // Unreachable, needed to appease compiler.
}
}
/* Utility function that creates an AccessControlContext that only has file
* read permissions.
*/
private static AccessControlContext getContext() {
CodeSource c = new CodeSource(null, (java.security.cert.Certificate[])null);
Permissions permissions = new Permissions();
/* Grant specific permission to read files. This is necessary, since otherwise the
* class loader can't read classes from disk.
*/
permissions.add(new FilePermission("*", "read"));
/* Construct an AccessControlContext from these permissions. */
return new AccessControlContext(new ProtectionDomain[] {new ProtectionDomain(c, permissions)});
}
public static void main(String[] args) {
/* Get a very restrictive AccessControlContext that does not allow for anything to run. */
AccessControlContext noPermissions = getContext();
/* Install a standard security manager to enable security. */
System.setSecurityManager(new SecurityManager());
/* Sit in an infinite loop using reflection to create Main objects. This code is
* run in a context where its only permissions are file reading.
*/
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@Override
public Void run() {
/* Continuously create new Main objects. */
Constructor<Main> ctor = getCtor();
try {
while (true) {
ctor.newInstance();
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}, noPermissions);
}
}
이 코드는 이제 완벽하게 잘 작동 - 그것은 어떠한 문제없이 Main
객체의 모든 종류를 구축합니다. 나는에 대한 혼란 스러워요 무엇
은 다음과 같다. AccessController
에 치아가 있으려면 보안 관리자를 켜야합니다. 나는 지금
/* Install a standard security manager to enable security. */
System.setSecurityManager(new SecurityManager());
를 호출하여이 작업을 수행, 내가이 사용자 정의
SecurityManager
에
기본
SecurityManager
에서이 설정을 변경한다고 가정하면 :이 때 발생하는 로그를 제외
/* Install a standard security manager to enable security. */
System.setSecurityManager(new SecurityManager() {
@Override
public void checkPermission(Permission p) {
/* Log the permission. */
System.out.println("Checking " + p);
super.checkPermission(p);
}
});
이 SecurityManager
은 이전과 동일하다 권한이 확인 된 다음 요청을 기본값 SecurityManager
으로 전달합니다.
Checking ("java.io.FilePermission" "/home/keith/Documents/secret-eclipse-workspace/Security Manager Test/bin/Main$2.class" "read")
Checking ("java.io.FilePermission" "/home/keith/Documents/secret-eclipse-workspace/Security Manager Test/bin/Main$2.class" "read")
Checking ("java.io.FilePermission" "/home/keith/Documents/secret-eclipse-workspace/Security Manager Test/bin/Main$2.class" "read")
Number created: 1
Number created: 2
Number created: 3
Number created: 4
Number created: 5
Number created: 6
Number created: 7
Number created: 8
Number created: 9
Number created: 10
Number created: 11
Number created: 12
Number created: 13
Number created: 14
Number created: 15
Checking ("java.lang.RuntimePermission" "createClassLoader")
java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "createClassLoader")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:372)
at java.security.AccessController.checkPermission(AccessController.java:559)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at Main$1.checkPermission(Main.java:51)
at java.lang.SecurityManager.checkCreateClassLoader(SecurityManager.java:611)
at java.lang.ClassLoader.checkCreateClassLoader(ClassLoader.java:274)
at java.lang.ClassLoader.<init>(ClassLoader.java:316)
at sun.reflect.DelegatingClassLoader.<init>(ClassDefiner.java:72)
at sun.reflect.ClassDefiner$1.run(ClassDefiner.java:60)
at sun.reflect.ClassDefiner$1.run(ClassDefiner.java:58)
at java.security.AccessController.doPrivileged(Native Method)
at sun.reflect.ClassDefiner.defineClass(ClassDefiner.java:57)
at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:399)
at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:396)
at java.security.AccessController.doPrivileged(Native Method)
at sun.reflect.MethodAccessorGenerator.generate(MethodAccessorGenerator.java:395)
at sun.reflect.MethodAccessorGenerator.generateConstructor(MethodAccessorGenerator.java:94)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:48)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at Main$2.run(Main.java:65)
at Main$2.run(Main.java:1)
at java.security.AccessController.doPrivileged(Native Method)
at Main.main(Main.java:58)
왜 내가 전에이 사용자 정의 SecurityManager
사용 후 다른 동작을 얻고있다 :이 변경하고 프로그램을 실행하면
은, 지금은 이전과 동일한 동작을 얻을? 두 경우 모두 기본값 인 SecurityManager
이 실제로 모든 보안 검사를 수행하는 것이므로 프로그램에서 이러한 경우 다른 결과를 산출하는 이유는 알 수 없습니다.
감사합니다. 당신의 SecurityManager
에
감사합니다! 이 코드를 어떻게 신뢰할 수 있습니까? 아니면 완전히 다른 접근법을 찾아야합니까? – templatetypedef
@templatetypedef 일반적으로, 정책 파일에 java.security.AllPermission 코드베이스를 부여 할 수 있습니다. –