问题
I'm trying to implement a @Restricted annotation, to secure controller methods in a way that users can only access them, when they are logged in and have a certain role. I'm on Tomcat 7 using JSF and CDI, so no EJB. The interceptor gets called as long as the annotation interface does not specify any parameters. As soon as I add a @Nonbinding Role value() default Role.ADMIN; parameter, neither the interceptor nor the controller method execute. No errors or exceptions either. Here is my code, I really don't know what's wrong with it:
Annotation:
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface Restricted {
@Nonbinding Role value() default Role.ADMIN; // ###
}
Interceptor:
@Interceptor
@Restricted
public class RoleBasedRestrictingInterceptor implements Serializable {
@Inject
ISecurityManager security;
@AroundInvoke
public Object intercept(final InvocationContext ctx) throws Exception {
final Restricted annotation = ctx.getClass().getAnnotation(Restricted.class);
log.info("Intercepted, required role is: {}", annotation.value()); // ###
log.info("User is logged in: {}", security.isLoggedIn());
return ctx.proceed();
}
}
Controller:
@Named("manageUsers")
@SessionScoped
public class ManageUsersBacking extends implements Serializable {
@Restricted(Role.ADMIN) // ###
public void testRestricted() {
log.info("testRestricted()");
}
}
The ### occurrences mark what has to be changed or removed to make it work again. The interceptor is properly defined in WEB-INF/beans.xml, since it works without the role parameter in my annotation.
16:04:33.772 [http-apr-8080-exec-11] INFO c.m.s.RoleBasedRestrictingInterceptor - User is logged in: true
16:04:33.772 [http-apr-8080-exec-11] INFO c.m.c.admin.ManageUsersBacking - testRestricted()
回答1:
After a long story [1] ... Today I revisited this particular problem and noticed it had nothing to do with CDI:
ctx.getClass().getAnnotation(Restricted.class)
Obviously, there is no class level annotation in my example. So getAnnotation() returns null. Instead I should have used the following:
ctx.getMethod().getAnnotation(Restricted.class)
Though I don't know why there where no exceptions whatsoever. Maybe some other things were going on, that I can no longer reproduce because ...
[1] ... I migrated my application to TomEE, which was a pain in the ass and took me more than a week. And I still need to deploy TomEE in production, behind an Apache proxy, so some configuration has still to be done. If it finally works out, it might have been worth the effort, for I also had some other CDI issues (e.g. injecting CDI beans into JAX-RS services did not work using Weld + Resteasy + Tomcat) that are now gone. I also like the EJB and container managed transaction stuff. But I don't think it's a good idea to praise TomEE whenever someone tries to use small parts or even a subset of Java EE together with Tomcat. Many of its API implementations are meant to work in various environments (even Java SE) and that is a good thing. So if you don't need TomEE for some of its advanced Java EE features, I can not recommend this move. Some problems will be gone, but others will emerge. And you can no longer choose freely among different API implementations. However, this is not a statement against TomEE. Being used to Tomcat I really love the idea of TomEE.
回答2:
if you switch to TomEE you'll don't need to depend (maven) on implementations, just api (use org.apache.openejb:javaee-api:6.0-4 with a provided scope
回答3:
It sounds like you have things setup correct (beans.xml and interceptor). Which CDI implementation are you using? If you're using Tomcat have you looked at using TomEE?
来源:https://stackoverflow.com/questions/15709203/cdi-interceptor-does-not-work-when-annotation-has-parameter