EJB 3 In Action wrote:
According to the above example, it uses the @RunAS (oh! S capital ) annotation to annotate a method, not the class. Is this valid?
it may be possible that some app servers don't complain when @RunAs is used on method level. But the specification itself is unambiguous here.
@RunAs can be used on method. Cancel bid will be invoked as a role of Admin.
I think there is some missunderstanding on how @RunAs works:
If no @RunAs would have been specified, bMethod would be called by a principal with role "Guest". Due to @RunAs it is called by a principal with role "Admin" and everything works fine.
@RunAs has no effect on the roles used to perform aMethod.
In the scenario above only "Guest" can perform aMethod. So, without @RunAs this role would be propagated to the call of bMetod() on bean b.
if you have specified a role of 'Guest', and we are using the annotation @RunAs("Admin"), this means Guest role will be replaced by Admin role for this class, to execute it. for other executions, default Guest role will apply.
Principal is more broader term then roles. If role is not specified, then principal is propagated to role. if principal is not specified, then role is propagated to principal. Otherwise, there will be a mapping from principal to role.
Correct me if i am wrong.
I think a Principal is a set of roles.
You can think of a principal simply as a user of the system. The system's principals are independent from ejb's and therefore it's the system administrator's responsibility to define principals (in practise: users and user groups).
In "declarative security" ejb's are secured by roles (using @RolesAllowed).
The link between principals and roles is provided by the deployer: He assigns each principal that uses the bean a corresponding role. This is done in the runtime deployment descriptor (at least for glassfish) and is specific to the app server.
If role is not specified, then principal is propagated to role. if principal is not specified, then role is propagated to principal
Consider the following scenario:
- Client C calls methodA() on bean A, which calls methodB() on bean B (code as above).
- The user logs in on the client as "Amandeep" and there is defined a corresponding principal Amandeep_Principal on app server 1 where A resides. The deployer has assigned Amandeep_Principal the role "Guest".
- Normally, when methodB() is called, Amandeep_Principal would be propagated to app server 2 where B resides. But you can circumvent this propagation using, say, @RunAs("Admin").
For this to work there must be a principal with role "Admin" on app server 1, say Admin_Principal (if there are several principals with role "Admin" glassfish chooses one coincidentally). From the perspective of app server 2, now methodB() is called by principal Admin_Principal.
Of course, Admin_Principal must be defined on app server 2, too, and the assigned role of Admin_Principal on bean B has to be "Admin". Otherwise the call of methodB() will result in an EJBAccessException.