/** * Copyright 2013-2016 Guoqiang Chen, Shanghai, China. All rights reserved. * * Author: Guoqiang Chen * Email: subchen@gmail.com * WebURL: https://github.com/subchen * * 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 jetbrick.template; import java.io.File; import java.lang.reflect.*; import java.security.AccessControlException; import java.util.*; import jetbrick.io.IoUtils; import jetbrick.util.StringUtils; /* * 默认的安全管理器。 * * @author Guoqiang Chen */ public final class JetSecurityManagerImpl implements JetSecurityManager { private final Set<String> blackList; private final Set<String> whiteList; private boolean disallowStaticMethod; private boolean disallowStaticField; private boolean disallowConstructor; public JetSecurityManagerImpl() { blackList = new HashSet<String>(); whiteList = new HashSet<String>(); disallowStaticMethod = false; disallowStaticField = false; disallowConstructor = false; } public void setConfigFile(String configFile) { String fileContent = IoUtils.toString(new File(configFile), "utf-8"); String[] lines = StringUtils.split(fileContent, '\n'); for (String line : lines) { addList(line); } } public void setNameList(List<String> nameList) { for (String line : nameList) { addList(line); } } public void setDisallowConstructor(boolean disallowConstructor) { this.disallowConstructor = disallowConstructor; } public void setDisallowStaticMethod(boolean disallowStaticMethod) { this.disallowStaticMethod = disallowStaticMethod; } public void setDisallowStaticField(boolean disallowStaticField) { this.disallowStaticField = disallowStaticField; } private void addList(String line) { line = line.trim(); if (line.length() == 0) { return; } char c = line.charAt(0); if (c == '+') { whiteList.add(line.substring(1)); } else if (c == '-') { blackList.add(line.substring(1)); } else { whiteList.add(line); } } /** * 是否允许进行访问. * * <p> * 其中参数 name 的格式. * <ul> * <li>java.lang:整个 package</li> * <li>java.lang.String:整个 Class</li> * <li>java.lang.String.<init>:构造函数</li> * <li>java.lang.Integer.MAX_VALUE :字段</li> * <li>java.lang.Integer.valueOf:方法</li> * </ul> * </p> * <p>默认是白名单,前面加 + 代表白名单,- 代表黑名单</p> */ private void checkAccess(String fullName) throws AccessControlException { String name = fullName; do { if (whiteList.contains(name)) { return; } if (blackList.contains(name)) { throw new AccessControlException("access denied for \'" + fullName + "\' because of \'" + name + "\' is in blacklist."); } int ipos = name.lastIndexOf('.'); if (ipos == -1) break; name = name.substring(0, ipos); } while (true); } @Override public void checkAccess(Class<?> cls) { checkAccess(cls.getName()); } @Override public void checkAccess(Constructor<?> constructor) throws AccessControlException { String fullName = constructor.getDeclaringClass().getName() + ".<init>"; if (disallowConstructor) { throw new AccessControlException("access denied for constructor: " + fullName); } checkAccess(fullName); } @Override public void checkAccess(Method method) throws AccessControlException { String fullName = method.getDeclaringClass().getName() + '.' + method.getName(); if (disallowStaticMethod && Modifier.isStatic(method.getModifiers())) { throw new AccessControlException("access denied for static method: " + fullName); } checkAccess(fullName); } @Override public void checkAccess(Field field) throws AccessControlException { String fullName = field.getDeclaringClass().getName() + '.' + field.getName(); if (disallowStaticField && Modifier.isStatic(field.getModifiers())) { throw new AccessControlException("access denied for static field: " + fullName); } checkAccess(fullName); } }