Grails Spring Security Configuration thru xml - security

i am new at grails spring security, and i wanted to know if it is possible to enable/disable security of in my app thru an xml entry.
rather than having
grails.plugins.springsecurity.active = true
I d like to read the value from a bean that i declared in my resources.xml file.
grails.plugins.springsecurity.active = com.myorg.util.BeanUtil.getBean("repositorySettings").getIsSecured()
Using this approach throws errors. is there a way that i can accomplish this, and read the true/false value from a bean in the resources.xml

It's somewhat possible. resources.xml and resources.groovy are loaded after the plugin is, but parsed before. So you can put code in resources.groovy that will run while it's being parsed, before the plugin loads the config, and determines whether it's enabled. But you can't use a bean for that since it wouldn't be ready until it's too late. This wouldn't be possible in resources.xml since that's just XML but resources.groovy allows Groovy code and bean definitions:
import com.pbbi.mimgr.util.BeanUtil
beans = {
def grailsApplication = springConfig.unrefreshedApplicationContext.grailsApplication
def securityConfig = grailsApplication.config.grails.plugins.springsecurity
securityConfig.active = BeanUtil.getBean('repositorySettings').isSecured
}
If BeanUtil accesses the ApplicationContext then this won't work. But if it's accessing singletons that aren't Spring beans it should be fine.

Related

How to properly create an instance of AnnotatedControllerConfigurer

I'm trying to define a configuration to create an ExecutionGraphQlService to wire into an existing application as a proof of concept, but I'm a bit confused about how to create an instance of a AnnotatedControllerConfigurer. Here is what I currently have settled upon.
AnnotatedControllerConfigurer annotatedControllerConfigurer = new AnnotatedControllerConfigurer();
annotatedControllerConfigurer.setApplicationContext(applicationContext);
annotatedControllerConfigurer.afterPropertiesSet();
annotatedControllerConfigurer.configure(runtimeWiringBuilder);
AnnotatedControllerConfigurer implements ApplicationContextAware, InitializingBean so it seems to expect to be initialized as a bean, but attempts to autowire an instance of it fail due to Could not autowire. No beans of 'AnnotatedControllerConfigurer' type found.
I've attempted constructor injection public ExecutionGraphQlService defaultExecutionGraphQlService(AnnotatedControllerConfigurer annotatedControllerConfigurer) as well as manual instantiation autowireCapableBeanFactory.autowireBean(annotatedControllerConfigurer) (which should be basically the same thing).
It seems like this class is not a bean, but expects to be managed by Spring's bean lifecycle? Is my approach the expected approach?
The AnnotatedControllerConfigurer type is meant to be a bean in the Spring container, and is using the bean lifecycle to setup the infrastructure.
Creating it as a bean (given other pieces are contributed as beans as well). The runtime wiring should be configured on the GraphQlSource directly.
#Configuration(proxyBeanMethods = false)
class GraphQlConfiguration {
#Bean
public AnnotatedControllerConfigurer annotatedControllerConfigurer() {
return new AnnotatedControllerConfigurer();
}
}

Override beans from an external library (Quarkus)

I want to override a bean that's used by Quarkus to disable authentication/authorization.
With the following implementation, it works that REST endpoints can be configured at start time to not be secured:
#Alternative
#Priority(1)
#ApplicationScoped
public class CustomOidcAuthController extends TestAuthController {
private static final Logger LOGGER = Logger.getLogger(CustomOidcAuthController.class);
#ConfigProperty(name = "quarkus.oidc.enabled", defaultValue = "false")
boolean quarkusOidcEnabled;
#PostConstruct
public void check() {
LOGGER.info("isAuthorizationEnabled(): " + isAuthorizationEnabled());
}
#Override
public boolean isAuthorizationEnabled() {
return quarkusOidcEnabled;
}
}
This is with the Bean residing in the same Quarkus module.
However, I want to externalize this class into a separate library and if I do this, it no longer works.
Noteworthy:
Yes, the #Priority of my bean (1) is higher than the default (3000)
The beans are discovered, if I explicitly inject them.
They are however not used, if I inject the subtype that Quarkus uses internally (either TestAuthController or AuthorizationController).
Therefore the endpoints are always secured
As can be seen here from the IntelliJ debugger
Currently I have an empty beans.xml, but with building a Jandex Index I also observe the same behavior (related How to create a Jandex index in Quarkus for classes in a external module)
I can get the behavior I want, if I use quarkus.arc.selected-alternatives=com.xxx.CustomOidcAuthController, however this is not preferable, since each Service using the library would need to configure this and this will certainly cause problems, because it can be easily forgotten.
Well, the priority of the TestAuthController is indeed 3000 and therefore it takes precedence. Injection of CustomOidcAuthController works because there's no other bean that has CustomOidcAuthController in its set of bean types.
In other words, it works as expected (and defined by the spec).
Yes, the #Priority of my bean (1) is higher than the default (3000)
According to CDI specification, an alternative with highest priority is selected. See this part of the CDI 2.0 specification.
Here is a CDI TCK test asserting that higher priority 'wins' during typesafe resolution.
Therefore, your approach is correct and you just need to make sure your custom bean is an alternative with priority value higher than that of TestAuthController.

Hibernate validator programmatic constraints declaration and JSF

I Have a JSF-2.2 web app on a WildFly 8.1 app server shiping Hibernate-validator 5.1
I want to set some constrainst programmaticaly using the fluent API, because they depends on the case for example a min and max of a #Size constraint could vary or a field could be #NotNull or not...
so I try to programmaticaly configure constraints such as describe here : http://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html_single/#section-programmatic-api
I do somthing like that to try (in a EJB #Singleton #Startup):
HibernateValidatorConfiguration configuration = Validation
.byProvider( HibernateValidator.class )
.configure();
ConstraintMapping constraintMapping = configuration.createConstraintMapping();
constraintMapping
.type( Car.class )
.property( "manufacturer", FIELD )
.constraint( new NotNullDef() )
.property( "licensePlate", FIELD )
.ignoreAnnotations()
.constraint( new NotNullDef() )
.constraint( new SizeDef().min( 2 ).max( 14 ) );
Validator validator = configuration.addMapping( constraintMapping )
.buildValidatorFactory()
.getValidator();
But then JSF don't use this new constraints mapping.
I can submit forms without problem even if I break the constraints programmaticaly set
I don't know how to configure the Validator or ValidatorFactory JSF is using or how to provide to JSF an other Validator or ValidatorFactory...
Or may be It's more about configuring WildFly server, something to do in a config file or JNDI, I don't have a clue...
EDIT
I try to bind new Validator and validator factory in JNDI
But I can't because "Naming context is read-only"
Hashtable jndiProperties = new Hashtable();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
Context context = new InitialContext(jndiProperties);
context.bind("java:comp/Validator", factory.getValidator());
context.bind("java:comp/ValidatorFactory", factory);
Thank you Hardy
As you proposed I post Hibenate Validator improvement
https://hibernate.atlassian.net/browse/HV-955
There is no way atm to do what you are after. Hibernate Validator has indeed the programmatic mapping, but it is a Hibernate Validator specific feature. There is no way to bootstrap this functionality in a Bean Validation way. I am saying this, since the only way to customize your ValidatorFactory and hence Validator instance within the container is via validation.xml. And there is no mechanism for the fluent API in this configuration file.
Your JNDI idea is in principal good, but as you say, it is only read only.
validation.xml allows for vendor specific properties though. One could imagine a property like org.hibernate.validator.config_factory=acme.MyConfig. The value of the property would point to a fully specified class which would contain some sort of factory method which returns the programmatic mapping to be added to the configuration. Unfortunately, such a property does not yet exist. You could open an issue here though ;-)

CDI extension, altering processed type

Using Weld 1.1.13.Final in test with Arquillian....
Let's say I inject into a field something volatile. Something like a property subject to change that I want the bean owning the injection point to receive change events. Thought about creating a CDI extension.
Caught ProcessAnnotatedType event and looking for all fields that have an custom annotation on field injection points:
<T> void pat(#Observes ProcessAnnotatedType<T> event, BeanManager bm) {
final AnnotatedType<T> target = event.getAnnotatedType();
for (AnnotatedField<? super T> field : target.getFields())
if (field.isAnnotationPresent(Value.class)) { // ignore that I don't check #Inject here for the moment
CtClass wrapper = pool.get(target.getJavaClass().getName());
ConstPool cp = wrapper.getClassFile().getConstPool();
CtMethod m = CtNewMethod.make(....)
....
wrapper.addMethod(m);
event.setAnnotatedType(bm.createAnnotatedType(wrapper.toClass()));
}
}
Had even grabbed thereafter all the injection points for fields and replaced the underlying WeldField with a new Field corresponding the "wrapper" type. Otherwise bean validation fails.
But this only works for stuff setup during startup not when for example Arquillian uses the Bean Manager to initialize a class that injects one of my "wraps". Things fail since the Bean Resolver uses the Type as a hash key to find beans.
Basically I don't think I can "mask" a class that is annotated (made into a bean) by the CDI with an extra method to receive custom events. Would have been cool but a Type is a Type (i.e. no idea how to proxy or fake the equals/hashCode).
Got it. Turns out the compute value function (google extension) inside the TypeSafeBeanResolver resolver (at least the CDI Weld implementation) is smart. If I just extend the class:
CtClass wrapper = pool.makeClass(target.getJavaClass().getName()+"Proxy");
wrapper.setSuperclass(pool.get(target.getJavaClass().getName()));
.....
final AnnotatedType<T> other = bm.createAnnotatedType(wrapper
.toClass());
then everything works fine. Tested capturing an event in a bean. Will post the code on a Gist with a comment.

Using Properties from ResourceBundle in ManagedProperty

I have a JSF Validator that I'm building that has properties in it that I would like to have loaded from a ResourceBundle. However, I'm not quite sure how to work this, as it isn't loading properly. Any ideas on how I can make this work?
I've tried using a #PostContruct to do it, but I'm getting the following error in Eclipse:
Access restriction: The type
PostConstruct is not accessible due to
restriction on required library
/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Classes/classes.jar
So, I'm not too sure what the best way to work this. A sample of what I'm talking about is below...
The validator...
#FacesValidator("usernameValidator")
public class UserNameValidator implements Validator {
#ManagedProperty(value="#{props_userNamePattern}")
private String userNamePattern;
#ManagedProperty(value="#{props_minUserNameLength}")
private int minUserNameLength;
#ManagedProperty(value="#{props_maxUserNameLength}")
private int maxUserNameLength;
public void validate(FacesContext context, UIComponent component, Object
value) throws ValidatorException {
//My validations here...
}
//Setters for the class properties
}
faces-config.xml
<resource-bundle>
<base-name>settings</base-name>
</resource-bundle>
settings.properties
props_userNamePattern = /^[a-z0-9_-]+$/
props_minUserNameLength = 3
props_maxUserNameLength = 30
The #ManagedProperty works on #ManagedBean classes only. The #PostConstruct will also not be the correct solution for your functional requirement. It is intented to be placed on a method which is to be executed when the class has been constructed and all dependency injections are been finished. The error which you're facing is caused by a specific combination of older Eclipse+JRE versions. If upgrading is not an option, you could disable the warning/error by Window > Preferences > Java > Compiler > Errors/Warnings > Deprecated and restricted API > Forbidden reference > Ignore.
As to your functional requirement, unfortunately no annotation which achieves that comes to mind. You could however get it programmatically.
String bundlename = "settings";
Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
ResourceBundle bundle = ResourceBundle.getBundle(bundlename, locale);
String usernamePattern = bundle.getString("props_userNamePattern");
// ...
You can do that in the constructor of the validator. When used properly a new instance will be created for every view anyway.
Adding to the correct answer of BalusC; In JSF 2.0/2.1 Validators, Converters, PhaseListeners, etc are a kind of 'second-class' citizen as they are not injection targets.
This also means you can't inject an entity manager or an EJB, which can sometimes be used for validation purposes.
In JSF 2.2 this is supposed to change:
All JSF lifecycle artifacts should be
CDI-aware and support
injection/JSR-299/JSR-330
(PhaseListeners, NavHandlers,
Components, ActionListeners,
everything.)
See: http://jcp.org/en/jsr/detail?id=344
Perhaps seam-faces might help for this situation?
http://docs.jboss.org/seam/3/faces/latest/reference/en-US/html/artifacts.html
http://docs.jboss.org/seam/3/faces/latest/reference/en-US/html/faces.messages.html

Resources