In the past I always implemented authorization with some very proprietary code having an #ApplicationScoped bean with methods like isUserInAnyOfTheseRoles(String... roles), which executes appropriate database queries. I always had to call these methods at the start of a protected EJB method/REST resource, making an if-statement and possibly throwing a "NotAuthorized"-exception.
For the future I consider using JakartaEE's security mechanisms so I am reading into it. I have a problem understanding the use of the #javax.annotation.security.DeclareRoles annotation.
Amongst others I read SO answer to ejb Security questions regarding Roles and Authentication. There it is said that
The #DeclareRoles annotation on the other hand is merely used to declare a list of roles; [...]. The EJB container does not require knowledge of these roles to enforce access control checks on business methods of an EJB; instead, the bean provider/developer may use these roles in isCallerInRole tests to ensure programmatic security.
If I understand it right I need to declare the roles I use programmatically with javax.security.enterprise.SecurityContext#isCallerInRole(String). So my class might look like the following.
#DeclareRoles({"ADD_ENTITY", "DELETE_ENTITY", "UPDATE_ENTITY", "SEE_ENTITY", "SEE_ENTITY_DETAILS", "SEE_RESTRICTED_DATA", "MERGE_ENTITY", "ATTACH_METADATA"})
public class PersonService {
#Inject SecurityContext ctx;
#RolesAllowed({"SEE_ENTITY"})
public Person getPerson(long id) {
if(ctx.isCallerInRole("SEE_ENTITY_DETAILS") {...}
else if(ctx.isCallerInRole("SEE_RESTRICTED_DATA") {...}
else {...}
}
...
}
1st question:
Now if I have another class, do I need to declare all the roles again?
#DeclareRoles({"ADD_ENTITY", "DELETE_ENTITY", "UPDATE_ENTITY", "SEE_ENTITY", "SEE_ENTITY_DETAILS", "SEE_RESTRICTED_DATA", "MERGE_ENTITY", "ATTACH_METADATA"})
public class CompanyService {
#Inject SecurityContext ctx;
#RolesAllowed({"SEE_ENTITY"})
public Company geCompany(long id) {
if(ctx.isCallerInRole("SEE_ENTITY_DETAILS") {...}
else {...}
}
...
}
In the mentioned answer the EJB spec is quoted with
The DeclareRoles annotation is specified on a bean class, where it serves to declare roles that may be tested by calling isCallerInRole [...]
2nd question: Is it correct that this declaration is only used by the programmatically access and not for the declarative part? So that I do not need to declare any roles if I only use the annotation #RolesAllowed.
3rd question: What is the reason for this "duplication"? For me it is just annoying to declare the roles (by the way I do have plenty of roles in my application) twice. I do not see the point in doing so, after all it is just a string. I need to write a custom javax.security.enterprise.identitystore.IdentityStore to map roles to a user. Aligning these roles in every EJB seems to be unnecessary.
4th question: In a comment to a similar question (Define #DeclareRoles annotation programmatically) I interpret that #DeclareRoles might by a ancient relic and is no longer needed if an IdentityStore is used. If that would be true, it would make things a little bit clearer to me.
Sorry for the four questions in one post, but it all tangled together somehow. Basically it is question 3 that haunts me the most.
Related
I know how to add a Bean to a CDI container during AfterBeanDiscovery. My problem is that what I really need to do is the equivalent of adding a new producer method with the equivalent of a particularly qualified parameter.
That is, I'd like to somehow programmatically create several of these:
#Produces
#SomeQualifier("x")
private Foo makeFoo(#SomeQualifier("x") final FooMaker fm) {
return fm.makeFoo();
}
...where the domain over which SomeQualifier's value element ranges is known only at AfterBeanDiscovery time. In other words, some other portable extension has installed two FooMaker instances into the container: FooMaker-qualified-by-#SomeQualifier("x") and FooMaker-qualified-by-#SomeQualifier("y"). Now I need to do the equivalent of making two producer methods to "match" them.
Nonbinding is not an option; I want this resolution to take place at container startup, not at injection time.
I am aware of BeanManager's getProducerFactory method, but the dozens if not hundreds of lines of gymnastics I'd have to go through to add the right qualifier annotation on each AnnotatedParameter "reachable" from the AnnotatedMethod I'd have to create by hand (to avoid generics issues) make me think I'm way off the beaten path here.
Update: So in my extension, I have created a private static method that returns a Foo, and has a FooMaker parameter. I've wrapped this in a hand-tooled AnnotatedMethod that reports SomeQualifier("x") etc. in its getAnnotations() method, and also reports SomeQualifier("x") etc. from its AnnotatedParameter's getAnnotations() method. Then I got a ProducerFactory from the BeanManager and feed that into a new Bean that I create, where I use it to implement the create and destroy methods. Everything compiles and so forth just fine.
(However, Weld (in particular) blows up with this usage, which leads me to think that I'm doing Really Bad Thingsā¢.)
Coming from a Guice background, I know that it is possible to seed an object value from a scope using.
scope.seed(Key.get(SomeObject.class), someObject);
I suppose one could do this by registering a Bean that gets a value from an AbstractBoundContext, but examples just seeding one value from a Custom Scope seem hard to find. How do I create a custom scope that seeds a value that can be injected elsewhere?
Edit:
I am currently using the following workaround, that can be injected in an interceptor to set the Configuration when entering the scope, and can then be injected through its thread local provider. I am still looking for options that feel less hacky / are more integrated with the scope/scope context system in Weld though.
#Singleton
public class ConfigurationProducer {
private final InheritableThreadLocal<Configuration> threadLocalConfiguration =
new InheritableThreadLocal<>();
#Produces
#ActiveDataSet
public ConfigurationConfiguration() {
return threadLocalConfiguration.get()
}
public void setConfiguration(Configuration configuration) {
threadLocalConfiguration.set(configuration);
}
}
The answer is to register a custom bean with the AfterBeanDiscovery event, like so:
event.addBean()
.createWith(ctx -> commandContext.getCurrentCommandExecution())
.addType(CommandExecution.class)
.addQualifier(Default.Literal.INSTANCE)
.scope(CommandScoped.class)
.beanClass(CommandExtension.class);
There is a quite sophisticated example available at https://github.com/weld/command-context-example
As for good user feedback, I am using messages on multiple sites in my webapplication.
To add a message, I simple use:
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(type, "", message));
I added variables for type and message, because it depends on different validation.
Well, I am using different ManagedBeans for different sites, this is just normal.
It came to my mind, what is the best practice for adding those messages in different ManagedBeans.
Currently, I am always using the above code snippet like over 30 times (and it will become more and more for sure).
Should I create a Bean with SessionScopedannotated or #ApplicationScoped? Do you have any other hints, that should I know?
Just hide away repeated static code into a reusable static method to make it more DRY ("Don't Repeat Yourself").
Design the static method in such way that you can ultimately refactor from this,
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(type, "", message));
to something like this,
Messages.addGlobalInfo(message);
or even with an import static com.example.Messages.*; (Eclipse: Ctrl+Shift+M the line):
addGlobalInfo(message);
It doesn't need to be a managed bean as it doesn't hold any state. Moreover, you should make the default constructor of such an utility class private, so Java/JSF can in first place already not construct it via new operator or Class#newInstance() in reflection. If you're using CDI, annotate it if necessary with #Typed with an empty value to prevent it from being registered as managed bean candidate via Bean<T>.
#Typed
public final class Messages {
private Messages() {}
// ...
}
JSF utility library OmniFaces has exactly this utility class: org.omnifaces.util.Messages.
May be just move this code to some utility class:
public void static addMessage(FacesMessage.Severity type, String message){
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(type, "", message));
}
Also you can create several methods with one argument: addInfoMessage, addErrorMessage, ...
I think i understood how CDI works and in order to dive deep in it, i would like to try using it with something real world example. I am stuck with one thing where i need your help to make me understand. I would really appreciate your help in this regard.
I have my own workflow framework developed using Java reflection API and XML configurations where based on specific type of "source" and "eventName" i load appropriate Module class and invoke "process" method on that. Everything is working fine in our project.
I got excited with CDI feature and wanted to give it try with workflow framework where i am planning inject Module class instead of loading them using Reflection etc...
Just to give you an idea, I will try to keep things simple here.
"Message.java" is a kind of Transfer Object which carries "Source" and "eventName", so that we can load module appropriately.
public class Message{
private String source;
private String eventName;
}
Module configurations are as below
<modules>
<module>
<source>A</source>
<eventName>validate</eventName>
<moduleClass>ValidatorModule</moduleClass>
</module>
<module>
<source>B</source>
<eventName>generate</eventName>
<moduleClass>GeneratorModule</moduleClass>
</module>
</modules>
ModuleLoader.java
public class ModuleLoader {
public void loadAndProcess(Message message){
String source=message.getSource();
String eventName=message.getEventName();
//Load Module based on above values.
}
}
Question
Now , if i want to implement same via CDI to inject me a Module (in ModuleLoader class), I can write Factory class with #Produce method , which can do that. BUT my question is,
a) how can pass Message Object to #Produce method to do lookup based on eventName and source ?
Can you please provide me suggestions ?
Thanks in advance.
This one is a little tricky because CDI doesn't work the same way as your custom solution (if I understand it correctly). CDI must have all the list of dependencies and resolutions for those dependencies at boot time, where your solution sounds like it finds everything at runtime where things may change. That being said there are a couple of things you could try.
You could try injecting an InjectionPoint as a parameter to a producer method and returning the correct object, or creating the correct type.
There's also creating your own extension of doing this and creating dependencies and wiring them all up in the extension (take a look at ProcessInjectionTarget, ProcessAnnotatedType, and 'AfterBeanDiscovery` events. These two quickstarts may also help get some ideas going.
I think you may be going down the wrong path regarding a producer. Instead it more than likely would be much better to use an observer especially based on what you've described.
I'm making the assumption that the "Message" transfer object is used abstractly like a system wide event where basically you fire the event and you would like some handler defined in your XML framework you've created to determine the correct manager for the event, instantiate it (if need be), and then call the class passing it the event.
#ApplicationScoped
public class MyMessageObserver {
public void handleMessageEvent(#Observes Message message) {
//Load Module based on above values and process the event
}
}
Now let's assume you want to utilize your original interface (I'll guess it looks like):
public interface IMessageHandler {
public void handleMessage(final Message message);
}
#ApplicationScoped
public class EventMessageHandler implements IMessageHandler {
#Inject
private Event<Message> messageEvent;
public void handleMessage(Message message) {
messageEvent.fire(message);
}
}
Then in any legacy class you want to use it:
#Inject
IMessageHandler handler;
This will allow you to do everything you've described.
May be you need somthing like that:
You need the qualifier. Annotation like #Module, which will take two paramters source and eventName; They should be non qualifier values. See docs.
Second you need a producer:
#Produces
#Module
public Module makeAmodule(InjectionPoint ip) {
// load the module, take source and eventName from ip
}
Inject at proper place like that:
#Inject
#Module(source="A", eventName="validate")
Module modulA;
There is only one issue with that solution, those modules must be dependent scope, otherwise system will inject same module regardles of source and eventName.
If you want to use scopes, then you need make source and eventName qualified parameters and:
make an extension for CDI, register programmatically producers
or make producer method for each and every possible combinations of source and eventName (I do not think it is nice)
I am very new to concept of IOC and I understand the fact that they help us resolve different classes in different contexts. Your calling class will just interact with Interface and Interface with decide which implementation to give you and it takes care of newing up the object.
Please do correct me if I am understanding is wrong because my question is based on that:
Now, I see this pattern very often in these projects:
private readonly IEmailService emailService;
private readonly ITemplateRenderer templateRenderer;
private readonly IHtmlToTextTransformer htmlToTextTransformer;
public TemplateEmailService(IEmailService emailService,
ITemplateRenderer templateRenderer,
IHtmlToTextTransformer htmlToTextTransformer)
{
this.emailService = emailService;
this.htmlToTextTransformer = htmlToTextTransformer;
this.templateRenderer = templateRenderer;
}
I understand that this helps using all the implementations of these classes without newing them up and also you don't have to decide WHICH implementaion to get, your IOC decides it for you, right?
but when I code like this, I do not even touch any IOC congiguration files. And again I am usin git for 2 days only but from all the tutorials that I have read, I was expecting my self to configure something which says "Resolve IParent to Child" class. But it works without me doing anything like it. Is it because there is only one implementaion of these interfaces? and If I do have more than one implementations then and then only I will have to configure resolved explicitly?
The code sample you have is a case of Constructor Injection.
In a traditional code, you would have a parameterless constructor, and in it you would "new-up" your objects like this:
IEmailService emailService = new EmailService();
So your code is explictly controlling which implementation gets assigned to the interface variable.
In IoC using constructor injection, control is inverted, meaning the container is "driving the bus" and is creating your TemplateEmailService object. When it is about to create it, the container looks at your constructor parameters (IEmailService , ITemplateRenderer , etc.) and feeds those objects to your class for use.
The IoC container can be configured so that interface A gets fulfilled by implementation B (or C) explicitly. Each one has a way to do it. Or it could do it by convention (IFoo fulfilled by Foo), or even attributes in classes, whatever.
So to answer your question-- you can explicitly define which implementations get used to fulfill certain interfaces. Got to read the IoC container docs for how to.
One more thing - "when you code like this", you technically don't have to be using an IoC container. In fact, your class should not have a direct reference to the container - it will maximize the reusability, and also allow easy testing. So you would wire-up interfaces to implementation classes elsewhere.