Как получить разрешения от web.xml
Я хотел бы знать, если есть лучший способ (без отражения), чтобы получить java.security.Permissions для конкретного URL-адреса и роли.
например:
boolean canAccess = SecurityController.isAllowedToAccessUrl("/pages/confirmOrders.action", Collections.singletonList(new UserPrincipal("Dave")));
будет работать со следующим ограничением (web.xml):
<security-constraint>
<web-resource-collection>
<web-resource-name></web-resource-name>
<url-pattern>/pages/confirmOrders.action</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>Dave</role-name>
</auth-constraint>
Код, который я написал ниже, работает хорошо. Что мне не нравится, так это то, что мне нужно использовать отражение для вызова getContextPolicy из DelegatingPolicy.getInstance() и вызова getPermissionsForRole из ContextPolicy.
import org.jboss.security.jacc.ContextPolicy;
import org.jboss.security.jacc.DelegatingPolicy;
import javax.security.jacc.PolicyConfigurationFactory;
import javax.security.jacc.PolicyContext;
import javax.security.jacc.PolicyContextException;
import javax.security.jacc.WebResourcePermission;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.Permissions;
import java.security.Principal;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SecurityController {
private static final Logger LOG = Logger.getLogger(SecurityController.class.getName());
static boolean isAllowedToAccessUrl(final String url, final List<Principal> principalRoles) {
initializeConfigurationInService();
boolean result = false;
for (Principal principalRole : principalRoles) {
try{
final ContextPolicy contextPolicy = getContextPolicy();
final Permissions permissions = getPermissionsFromContextPolicy(contextPolicy, principalRole.getName());
result |= permissions.implies(new WebResourcePermission(url, new String[] {"GET","POST"}));
}catch (Exception e){
LOG.log(Level.SEVERE, "checkAllowed failed checking if : ", e);
}
}
return result;
}
private static void initializeConfigurationInService() {
try {
final PolicyConfigurationFactory policyConfigurationFactory = PolicyConfigurationFactory.getPolicyConfigurationFactory();
policyConfigurationFactory.getPolicyConfiguration(PolicyContext.getContextID(), false);
} catch (PolicyContextException | ClassNotFoundException e) {
LOG.log(Level.INFO, "initializeConfigurationInService", e);
}
}
private static Permissions getPermissionsFromContextPolicy(ContextPolicy contextPolicy, String loginName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
final Method getPermissionsForRole = contextPolicy.getClass().getDeclaredMethod("getPermissionsForRole", String.class);
getPermissionsForRole.setAccessible(true);
return (Permissions) getPermissionsForRole.invoke(contextPolicy, loginName);
}
private static ContextPolicy getContextPolicy() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
final DelegatingPolicy delegatingPolicy = DelegatingPolicy.getInstance();
final Method getContextPolicy = delegatingPolicy.getClass().getDeclaredMethod("getContextPolicy", String.class);
getContextPolicy.setAccessible(true);
return (ContextPolicy) getContextPolicy.invoke(delegatingPolicy, PolicyContext.getContextID());
}
}
Я прочитал программно получить ограничения безопасности из web.xml, но нашел это не очень полезным.
Любые комментарии, идеи действительно приветствуются. Спасибо!
1 ответ
Аналогичный стандартный метод для выполнения функции 'isAllowedToAccessUrl` доступен в Java EE 8.
boolean hasAccessToWebResource(String resource, String... methods)
Проверяет, имеет ли вызывающая сторона доступ к предоставленному "веб-ресурсу", используя указанные методы, как указано в разделе 13.8 спецификации сервлета. Вызывающая сторона имеет доступ, если веб-ресурс либо не защищен (ограничен), либо если он защищен ролью, и вызывающая сторона находится в этой роли.
Смотрите: SecurityContext # hasAccessToWebResource
Благодаря комментарию Uux я смог сократить свой код и избавиться от использования рефлексии. Теперь я могу проверить, разрешено ли определенной роли получать доступ к определенному URL в моем коде.
работоспособный код ниже:
import javax.security.jacc.WebResourcePermission;
import java.security.CodeSource;
import java.security.Policy;
import java.security.Principal;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
public class SecurityController {
private static final Logger LOG = Logger.getLogger(SecurityController.class.getName());
static boolean isAllowedToAccessUrl(final String url, final List<Principal> principalRoles) {
try {
final CodeSource codesource = new CodeSource(null, (Certificate[]) null);
final Principal[] principals = principalRoles.toArray(new Principal[0]);
final ProtectionDomain domain = new ProtectionDomain(codesource, null, null, principals);
return Policy.getPolicy().implies(domain, (new WebResourcePermission(url, new String[] {"GET", "POST"})));
} catch (Exception e) {
LOG.log(Level.SEVERE, "checkAllowed failed checking if : ", e);
}
return false;
}
}