Мне было интересно, можно ли получить полный список ролей безопасности, определенных в файле web.xml в java-коде? И если да, то как это сделать?
Мне известен метод isUserInRole, но я также хочу обрабатывать случаи, когда роль запрошена, но не определена (или написана иначе) в файле web.xml.




Насколько мне известно, в API сервлетов это невозможно сделать. Однако вы можете напрямую проанализировать web.xml и самостоятельно извлечь значения. Я использовал dom4j ниже, но вы можете использовать все, что вам нравится, для обработки XML:
protected List<String> getSecurityRoles() {
List<String> roles = new ArrayList<String>();
ServletContext sc = this.getServletContext();
InputStream is = sc.getResourceAsStream("/WEB-INF/web.xml");
try {
SAXReader reader = new SAXReader();
Document doc = reader.read(is);
Element webApp = doc.getRootElement();
// Type safety warning: dom4j doesn't use generics
List<Element> roleElements = webApp.elements("security-role");
for (Element roleEl : roleElements) {
roles.add(roleEl.element("role-name").getText());
}
} catch (DocumentException e) {
e.printStackTrace();
}
return roles;
}
Вот версия ответа Яна с использованием более нового DOM API:
private List<String> readRoles() {
List<String> roles = new ArrayList<>();
InputStream is = getServletContext().getResourceAsStream("/WEB-INF/web.xml");
try {
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = builder.parse(new InputSource(is));
NodeList securityRoles = doc.getDocumentElement().getElementsByTagName("security-role");
for (int i = 0; i < securityRoles.getLength(); i++) {
Node n = securityRoles.item(i);
if (n.getNodeType() == Node.ELEMENT_NODE) {
NodeList roleNames = ((Element) n).getElementsByTagName("role-name");
roles.add(roleNames.item(0).getTextContent().trim()); // lets's assume that <role-name> is always present
}
}
} catch (ParserConfigurationException | SAXException | IOException e) {
throw new IllegalStateException("Exception while reading security roles from web.xml", e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
logger.warn("Exception while closing stream", e);
}
}
}
return roles;
}
Жаль, что контейнер не предлагает никакой возможности получить эту информацию, но это кажется прекрасным обходным решением. Спасибо!