Пользовательская аннотация JSF
Я хотел сделать пользовательскую аннотацию для проверки безопасности некоторых функций моего веб-приложения JSF. В целях безопасности я использую безопасность Tomcat с JaaS, поэтому в моем распоряжении нет безопасности, управляемой приложением.
Что на самом деле нужно сделать, так это создать аннотацию для моих методов в Backing Bean, таких как Spring Security (@Secured("role")). Моя система безопасности реализована таким образом, что каждая функция является ролью, и вы можете динамически создавать "пользовательские роли", которые хранятся в БД, и когда кто-то регистрирует все (функции) роли в этой "пользовательской роли", будет установлен в безопасности Tomcat как роли.
Итак, теперь у меня есть этот кусок кода, чтобы проверить, может ли мой пользователь получить доступ к функции:
public static void checkSecurity(final String function) {
final FacesContext facesContext = FacesContext.getCurrentInstance();
try {
if (facesContext.getExternalContext().getRemoteUser() == null) {
facesContext.getExternalContext().redirect("login.xhtml");
return;
}
if (!facesContext.getExternalContext().isUserInRole(function)) {
facesContext.getExternalContext().redirect("restricted.xhtml");
return;
}
} catch (final Exception ex /* Mandatory "IOException e" will be caught + all other exceptions. */) {
facesContext.getExternalContext().setResponseStatus(403); // HTTP Status 403: Forbidden. Can also throw 401.
facesContext.responseComplete();
}
}
Теперь я должен вызвать этот SecurityUtil.checkSecurity("name_of_function"); в каждом методе. Но я хочу иметь аннотацию, подобную этой @CustomSecurity("function_name_role").
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomSecurity {
// Single Element called value.
String value();
}
И когда метод имеет эту аннотацию, функция checkSecurity должна автоматически выполняться. Поэтому мне нужно отсканировать эту аннотацию в определенный момент или создать какой-нибудь actionlistener. У JSF должно быть несколько вариантов для этого, но все форумы, которые я нашел на этом, действительно не помогают.
У кого-нибудь есть идеи?
РЕДАКТИРОВАТЬ: я пробовал этот блог, он работает, но только на действие компонента (и компоненты не отображаются, если у вас нет роли). Так насколько это безопасно, когда люди пытаются взломать структуру JSF. И я предпочитаю использовать его на каждом методе.
public class SecurityActionListener extends ActionListenerImpl implements ActionListener {
private static final Logger LOGGER = FacesLogger.APPLICATION.getLogger();
@SuppressWarnings("unused")
@Override
public void processAction(final ActionEvent event) {
final FacesContext context = FacesContext.getCurrentInstance();
final Application application = context.getApplication();
final ConfigurableNavigationHandler navHandler = (ConfigurableNavigationHandler) application.getNavigationHandler();
// Action stuff
final UIComponent source = event.getComponent();
final ActionSource actionSource = (ActionSource) source;
MethodBinding binding;
binding = actionSource.getAction();
final String expr = binding.getExpressionString();
if (!expr.startsWith("#")) {
super.processAction(event);
return;
}
final int idx = expr.indexOf('.');
final String target = expr.substring(0, idx).substring(2);
final String t = expr.substring(idx + 1);
final String method = t.substring(0, (t.length() - 1));
final MethodExpression expression = new MethodExpressionMethodBindingAdapter(binding);
final ELContext elContext = context.getELContext();
final ExpressionFactory factory = context.getApplication().getExpressionFactory();
final ValueExpression ve = factory.createValueExpression(elContext, "#{" + target + '}', Object.class);
final Object result = ve.getValue(elContext);
// Check if the target method is a secured method
// and check security accordingly
final Method[] methods = result.getClass().getMethods();
for (final Method meth : methods) {
if (meth.getName().equals(method)) {
if (meth.isAnnotationPresent(CustomSecurity.class)) {
final CustomSecurity securityAnnotation = meth.getAnnotation(CustomSecurity.class);
System.out.println("Function to check security on: " + securityAnnotation.value()); // TODO TO LOG
SecurityUtil.checkSecurity(securityAnnotation.value());
} else {
super.processAction(event);
}
break;
}
}
}
}
И это в лицах-config.xml:
<action-listener>
com.nielsr.randompackagebecauseofnda.SecurityActionListener
</action-listener>
Этот блог также может быть ответом, но я не знаю, как он будет работать с моей безопасностью JaaS Tomcat, потому что безопасность находится в отдельном проекте, развернутом в виде отдельного JAR-файла в папке lib tomcat.
Но я на самом деле не знаю, что мне нужно обезопасить свои бобы. Потому что я настроил все функции (или роли, см. Выше), которые находятся на 1 странице в Web.xml, как ограничения безопасности. И я рендеринг компонентов на странице, только если у вас есть права или "function_role" на этот компонент. Так это достаточно надежно? Или, если у кого-то есть право на функцию на странице, он может сам визуализировать компоненты и взломать мой сайт?
Я не настолько знаком с JSF, чтобы знать это, что происходит на этом дополнительном уровне абстракции JSF между Controller и View? (Я скорее разработчик Spring MVC, но из-за требований я должен использовать JSF, но приятно расширять свои знания.)
1 ответ
Вы можете "сканировать свои аннотации", используя
http://code.google.com/p/reflections/
С уважением