I basically understand the functions of #DeclareRoles and #RolesAllowed, but I'm not sure where to add the #DeclareRoles correctly. I testet with a vaadin application with ejb session beans and cdi in glassfish 4. The application is packed as war not as ear.
#DeclareRoles on no class:
Obviously nothing works. HttpServletRequest.isUserInRole() and SessionContext.isCallerInRole() are always returning false. #RolesAllowed always denies access.
#DeclareRoles on the Servlet:
#RolesAllowed and HttpServletRequest.isUserInRole() are working as expected. SessionContext.isCallerInRole() is always returning false.
#DeclareRoles on a session bean:
#RolesAllowed, HttpServletRequest.isUserInRole() and SessionContext.isCallerInRole() are working as expected. Even if SessionContext.isCallerInRole() is called in a different session bean than the one with #DeclareRoles
My question now are:
Where is the right place to put #DeclareRoles?
Is it ok to set it only once or should it annotate every bean that uses SessionContext.isCallerInRole() or #RolesAllowed?
Method permissions can be specified on the class, the business methods of the class, or both. Method permissions can be specified on a method of the bean class to override the method permissions value specified on the entire bean class. The following annotations are used to specify method permissions:
#DeclareRoles: Specifies all the roles that the application will use, including roles not specifically named in a #RolesAllowed annotation. The set of security roles the application uses is the total of the security roles defined in the #DeclareRoles and #RolesAllowed annotations.
The #DeclareRoles annotation is specified on a bean class, where it serves to declare roles that can be tested (for example, by calling isCallerInRole) from within the methods of the annotated class. When declaring the name of a role used as a parameter to the isCallerInRole(String roleName) method, the declared name must be the same as the parameter value.
The following example code demonstrates the use of the #DeclareRoles annotation:
#DeclareRoles("BusinessAdmin")
public class Calculator {
...
}
The syntax for declaring more than one role is as shown in the following example:
#DeclareRoles({"Administrator", "Manager", "Employee"})
#RolesAllowed("list-of-roles"): Specifies the security roles permitted to access methods in an application. This annotation can be specified on a class or on one or more methods. When specified at the class level, the annotation applies to all methods in the class. When specified on a method, the annotation applies to that method only and overrides any values specified at the class level.
To specify that no roles are authorized to access methods in an application, use the #DenyAll annotation. To specify that a user in any role is authorized to access the application, use the #PermitAll annotation.
When used in conjunction with the #DeclareRoles annotation, the combined set of security roles is used by the application.
The following example code demonstrates the use of the #RolesAllowed annotation:
#DeclareRoles({"Administrator", "Manager", "Employee"})
public class Calculator {
#RolesAllowed("Administrator")
public void setNewRate(int rate) {
...
}
}
#PermitAll: Specifies that all security roles are permitted to execute the specified method or methods. The user is not checked against a database to ensure that he or she is authorized to access this application.
This annotation can be specified on a class or on one or more methods. Specifying this annotation on the class means that it applies to all methods of the class. Specifying it at the method level means that it applies to only that method.
The following example code demonstrates the use of the #PermitAll annotation:
import javax.annotation.security.*;
#RolesAllowed("RestrictedUsers")
public class Calculator {
#RolesAllowed("Administrator")
public void setNewRate(int rate) {
//...
}
#PermitAll
public long convertCurrency(long amount) {
//...
}
}
#DenyAll: Specifies that no security roles are permitted to execute the specified method or methods. This means that these methods are excluded from execution in the Java EE container.
The following example code demonstrates the use of the #DenyAll annotation:
import javax.annotation.security.*;
#RolesAllowed("Users")
public class Calculator {
#RolesAllowed("Administrator")
public void setNewRate(int rate) {
//...
}
#DenyAll
public long convertCurrency(long amount) {
//...
}
}
The following code snippet demonstrates the use of the #DeclareRoles annotation with the isCallerInRole method. In this example, the #DeclareRoles annotation declares a role that the enterprise bean PayrollBean uses to make the security check by using isCallerInRole("payroll") to verify that the caller is authorized to change salary data:
#DeclareRoles("payroll")
#Stateless
public class PayrollBean implements Payroll {
#Resource SessionContext ctx;
public void updateEmployeeInfo(EmplInfo info) {
oldInfo = ... read from database;
// The salary field can be changed only by callers
// who have the security role "payroll"
Principal callerPrincipal = ctx.getCallerPrincipal();
if (info.salary != oldInfo.salary && !ctx.isCallerInRole("payroll")) {
throw new SecurityException(...);
}
...
}
...
}
The following example code illustrates the use of the #RolesAllowed annotation:
#RolesAllowed("admin")
public class SomeClass {
public void aMethod () {...}
public void bMethod () {...}
...
}
#Stateless
public class MyBean extends SomeClass implements A {
#RolesAllowed("HR")
public void aMethod () {...}
public void cMethod () {...}
...
}
More information:
Securing Enterprise Beans
Related
I have a configuration class, which I inject into another class.
Configuration class looks as follows:
#RequestScoped
public class Configuration {
#ConfigProperty(name = "VALUE")
public String value;
public String getValue() {
return value;
}
}
This configuration is injected into the following place:
#ApplicationScoped
public class EndpointImpl implements Endpoint {
private Configuration configuration;
#Inject
public EndpointImpl(Configuration configuration) {
this.configuration = configuration;
System.out.println("configuration.value=" + configuration.value);
System.out.println("configuration.getValue()=" + configuration.getValue());
System.out.println("configuration.value=" + configuration.value);
}
Logs printed after going through constructor:
configuration.value=null
configuration.getValue()=someValue
configuration.value=null
I added postConstructor with the below similar code:
#PostConstruct
public void postConstruct(){
System.out.println("configuration.value="+configuration.value);
System.out.println("configuration.getValue()="+configuration.getValue());
System.out.println("configuration.value="+configuration.value);
}
and the result is the same.
Everything works fine as long as the value is retrieved through the getter method. When I try to retrieve it through the public field it returns null. I thought that, when CDI completes the process of building the bean, the fields inside the class will be set to appropriate values.
Why does it behave in such a way?
This is expected, because your Configuration bean is #RequestScoped. The request scope is one of so-called normal scopes, and whenever you #Inject a normal-scoped bean, you will always get a so-called client proxy.
The client proxy exists to lookup the correct bean instance and forward method invocations to it. In this case, it will lookup the bean instance for current request.
So, when you're accessing fields, you're accessing them on the client proxy -- not on the instance that pertains to the current request.
Whenever you inject a normal-scoped bean, never access fields directly. Always call methods. You may access fields directly on #Singleton and #Dependent beans, because they don't come up with a client proxy.
I am learning spring :)
I have following doubts,
Does spring creates proxy object for every bean even if I have not used annotations for example #Transactional which I think need proxy.
I read following in spring documentation
Note that calls to static #Bean methods will never get intercepted by the container, not even within #Configuration classes (see above). This is due to technical limitations: CGLIB subclassing can only override non-static methods. As a consequence, a direct call to another #Bean method will have standard Java semantics, resulting in an independent instance being returned straight from the factory method itself.
a. Spring does not return proxy object in following example because of static method which is cannot override. So it will return original object here. Am I right?
#Configuration
public class Config {
#Bean
public static Student student() {
return new Student();
}
}
b. What is meaning of "Note that calls to static #Bean methods will never get intercepted by the container, not even within #Configuration classes"
a. Yes, you are correct. You will get the original object.
b. student() method is inside the class Config which is annotated with #Configuration annotation. All the methods which are annotated with #Bean inside #Configuration class are intercepted by spring by creating proxies. So as your method is static and though it is inside Config class, it will not be intercepted by Spring and no proxies will be created.
I successfully configured spring-security-oauth2 so that external apps can authenticate with my application. However based on the external app and based on what the user allows, only a subset of my API should be accessible to clients. The available subset is determined by the OAuth Scopes.
In classic Spring applications I could use #PreAuthorize to enforce boundaries based on roles:
#Controller
public class MyController {
#PreAuthorize("hasRole('admin')")
#RequestMapping("...")
public String doStuff() {
// ...
}
}
How do I do the same when using OAuth and with Scopes instead of roles?
Spring OAuth ships with the OAuth2MethodSecurityExpressionHandler, a class that adds the ability to do such checks using the #PreAuthorize expressions. All you need to do is register this class, e.g. like this if you are using Javaconfig:
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public static class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
#Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new OAuth2MethodSecurityExpressionHandler();
}
}
Now you can simply use:
#PreAuthorize("#oauth2.hasScope('requiredScope')")
to secure your request methods. To see which further methods are available besided hasScope check the class OAuth2SecurityExpressionMethods.
The downside is that OAuth2MethodSecurityExpressionHandler extends the DefaultMethodSecurityExpressionHandler and thus you cannot combine it with other classes that also extend this class.
As an alternative you could also map OAuth scopes to classic user roles.
I have spring controller with several (REST) endpoints. I want to bring up multiple instances of this controller where each instance would have few endpoints selectively enabled/disabled.
Based on my reading so far, togglz provides feature flipping, but it doesnt enable/disable the REST endpoints (togglz provides API so that caller code can check if a feature is enabled); ff4j seems to be another alternative, but it was not very obvious from the documentation if it can enable/disable REST end points
I read the thread Feature Toggling Java Annotations but it is a longer implementation. Is there any package that I can use to specify the endpoints that need to be enabled/disabled in a configuration file and use annotation on REST endpoints to disable/enable them (this way the logic in my method stays untouched and minimizes the testing)
A class with the #Bean or #Component will be loaded by spring on startup through the bean visitor mechanism. To exclude this bean from the Spring context at startup you can create a BeanPostProcessor(here) and check for dedicated annotation BUT as far as I understand, you cannot put the bean back to the context at runtime.
As a consequence, you must make this bean 'intelligent' to perform the correct operation/mock (or send 503 HTTP code) when requests come in.
FF4j can indeed help you implementing this behaviour but not with a single annotation on top of your REST Controller. What you could do :
Create an interface, annotate the interface with the dedicated FF4J annotation
Create 2 implementations of the interface, each time with a different name
Use FF4J to choose an implementation or another at runtime.
Here some code snippet to get the idea :
public interface GreetingService {
#Flip(name = "theFeatureIDToToggle", alterBean = "greeting.french")
String sayHello(String name);
}
#Component("greeting.french")
public class GreetingServiceFrenchImpl implements GreetingService {
public String sayHello(String name) {return "Bonjour " + name;
}
#Component("greeting.english")
public class GreetingServiceEnglishImpl implements GreetingService {
public String sayHello(String name) {return "Hello " + name;
}
//... import
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:applicationContext-ff4j-aop-test.xml")
public class FeatureAdvisorTest {
#Autowired
private FF4j ff4j;
#Autowired
#Qualifier("greeting.english")
private GreetingService greeting
#Test
public void testAnnotatedFlipping_with_alterBean() {
ff4j.disable("theFeatureIDToToggle");
Assert.assertTrue(greeting.sayHello("CLU").startsWith("Hello"));
ff4j.enable("theFeatureIDToToggle");
Assert.assertTrue(greeting.sayHello("CLU").startsWith("Bonjour"));
}
}
You can toggle a single method or the whole class, as you wish all samples are available here.
I am using Seam to inject beans to my controller using #In annotation. The injected class has a custom annotation, when calling injectedClass.getClass().getAnnotation(annotationClass) it returns null.
When debug I found that Seam passes a proxy instance so getClass() returns InjectedClass_$$_javassist_seam_5 which doesn't have my custom annotation.
How I can get my custom annotation from the proxy class?
Here's how my classes look like:
#CustomAnnotation(value="myvalue")
#Name("myAnnotatedClass")
public class MyAnnotatedClass extends SuperClass {...}
#Scope(ScopeType.SESSION)
#Name("myController")
public class MyController {
#In("#{myAnnotatedClass}")
private MyAnnotatedClass myAnnotatedClass;
public void actionMethod(){
//call another class which call myAnnotatedClass.getClass().getAnnotation(CustomAnnotation.class)
//then do some reflection for MyAnnotatedClass fields
}
}
Good question.
When you call a method by using Seam, it is intercepted by a proxy. And this one enables #In or #Out-jection. But There is an exception to this rule: it does not work when you call an internal method
So try this code
#Name
public class Service {
#In
private MyAnnotatedClass myAnnotatedClass;
public void myInterceptedMethod() {
// internal method bypass interceptor
// So #In or #Out-jection is not enabled
internalMethod();
}
private void internalMethod() {
System.out.println(myAnnotatedClass.getClass().getAnnotation(annotationClass));
}
}
Added to original answer
You want to retrieve an annotation from your bean. But, because of method interceptor, myAnnotatedClass.getClass() returns a proxy object, not the bean class itself.
For each bean class, Seam creates a Component definition, in which is stored in the application context. The name of the attribute follows this pattern: component name plus .component. So if you have a bean like this one
#Name("myBean")
public class MyBean {
}
Its Componet definition is stored in the attribute myBean.component
So inside your method, you can use
Component myBeanComponentDefinition = (Component) Context.getApplicationContext().get("myBean.component");
Now you can call
myBeanComponentDefinition.getBeanClass().getAnnotation(CustomAnnotation.class);
regards,
If you want less "ComponentDefinition" overbloat, you could also use this which also works for CDI and Spring:
Class.forName(myBean.getClass().getCanonicalName().substring(0,myBean.getClass().getCanonicalName().indexOf("$"))).getAnnotation(MyAnnotation.class)