Spring Security - Custom PreAuthorize Annotation? - spring-security

I'm guessing the answer is no here, but I was wondering if there was a way to create a custom annotation like this:
#Documented
#Inherited
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.TYPE, ElementType.METHOD})
#PreAuthorize("hasAuthority('" + PermissionRequired.value() + "')") //doesn't work
public #interface PermissionRequired {
String value();
}
So I can do this:
#PermissionRequired("CREATE_USER")
public User createuser(User newUser){
//..
}
But there doesn't seem to be a way to refer to the composing annotation, like I'm doing above. This doesn't look like something #AliasFor would solve, as I'm not using the field directly, I'm concatenating it with another string.
My goal here is to create security annotations that do not require any SpEl.

JSR-250 to the rescue!
Enable it on your application class:
#EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
public class MyApplication {
//..
}
Use their annotation:
#RolesAllowed({"ROLE_CREATE_USER"})
public User createuser(User newUser){
//..
}
It seems to require "ROLE_" prefixes on your authorities, though.

Related

Jersey 2 per-request #Context injection

Overview
In Jersey 2, can I inject a custom, request-specific value into my resource? Specifically, I would like to inject a MyThing which can be derived from my custom security context MySecurityContext. I would like to inject MyThing directly to make the code clean.
Is there any way to do this? According to this question it can't be done using a ContextResolver although this article and this example suggest it might be possible.
What Works
Using an auth filter, I am able to set my custom security context using code like this:
#Provider
public class HttpTokenAuthFilter implements IComposableJaxRsAuthFilter {
#Override
public boolean doAuth(ContainerRequestContext requestContext) throws WebApplicationException {
// error handling omitted
requestContext.setSecurityContext(MySecurityContext.fromHeaders(requestContext));
}
}
... and then in my resource I can pull a value from it:
#Path("/foo")
public class MyResource {
#Context
private SecurityContext securityContext;
#Get
public String doGetFoo() {
MyThing myThing = ((MySecurityContext)securityContext).getThing();
// use myThing to produce a result
}
Where I'm Stuck
... however, since this is going to be repeated a lot, I would much rather just write:
#Context
private MyThing myThing;
I tried defining a ContextResolver. I see it getting constructed, but I never see it getting invoked, so I have not yet tried any of the techniques linked above. Is this even the correct class to be using?
#Provider
public class MyThingResolver implements ContextResolver<MyThing> {
public MyThingResolver() {
System.out.println("ctor");
}
#Override
public MyThing getContext(Class type) {
System.out.println("getContext");
if (type.equals(MyThing.class)) {
return new MyThing(); // TODO: SHOULD ACTUALLY USE CURRENT MySession
}
return null;
}
}
Almost the solution
Per this answer and the refinements specified at this followup, it's almost possible to accomplish the injection using a Factory. The only caveat is, you must inject MyThing via a Provider, otherwise it's going to get created (with the default SecurityContext) before the filter runs and swaps in the MySecurityContext.
The factory code looks like this:
public class MyThingFactory implements Factory<MyThing> {
#Context
private SecurityContext securityContext;
#Override
public MyThing provide() {
return ((MySecurityContext)securityContext).getThing();
}
#Override
public void dispose(MyThing session) {
}
}
The resource can then inject it like this:
#Context
private Provider<MyThing> myThingProvider;
... and consume it like this:
MyThing myThing = myThingProvider.get();
// use myThing
The factory registration in the AbstractBinder looks like this:
this.bindFactory(MyThingFactory.class) //
.to(MyThing.class) //
.in(RequestScoped.class);
(Edit) Proxies to the Rescue!
Per the comment from #peeskillet, it is possible to get rid of the Provider by proxying MyThing. (Per # jwells131313, MyThing must therefore be an interface or a proxy-able class.)
The binding then looks like this:
this.bindFactory(MyThingFactory.class) //
.to(MyThing.class) //
.proxy(true) //
.in(RequestScoped.class);
and injection finally works as desired:
#Context
private MyThing myThing;

Customize sorting in criteria

I found grails criteria and want to customize sorting options.
E.g. I have domain Book and I want to make some criteria:
Book.createCriteria().list {
//some code like ilike('name', 'book')
...
order(params.sort, params.order)
}
I want to make specific sorting rule, e.g. by name.trim().
How can I do this?
Based on a solution provided here, by extending the hirbernate Order class, you can customize it to accept functions and use it with createCriteria.
I wont be surprised, if there is a nicer and easier approach since this source is pretty old and also Grails is cooler than this :D
First you need a class extending Hibernate Order:
Originally by:spostelnicu
public class OrderBySqlFormula extends Order {
private String sqlFormula;
protected OrderBySqlFormula(String sqlFormula) {
super(sqlFormula, true);
this.sqlFormula = sqlFormula;
}
public String toString() {
return sqlFormula;
}
public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
return sqlFormula;
}
public static Order sqlFormula(String sqlFormula) {
return new OrderBySqlFormula(sqlFormula);
}
}
Then you can pass instance of this class to your createCriteria:
def ls = Domain.createCriteria().list {
order OrderBySqlFormula.sqlFormula("TRIM(name)")
}
Note1: You can pass any formula to sqlFormula as long as the underlying database accepts it.
Note2: Using such approach might cause migration challenges.
Hope it helps

#PreAuthorize: reference property in implementing class

I have service interface
public interface CompoundService<T extends Compound> {
T getById(final Long id);
//...
}
and abstract implementation
public abstract class CompoundServiceImpl<T extends Compound>
implements CompoundService<T> {
//...
private Class<T> compoundClass;
//...
}
Every implementation of Compound requires it's own service interface which extends CompoundService and it's own service class which extends CompoundServiceImpl.
I would now like to add basic security uisng annotations to my methods in CompoundService. As far as I understood I must add them in the interface not the actual implementation. Since a user can have different roles for different implementations of Compound, i must take this into account. Meaning in #PreAuthorize I would like to get the name of the Compound implementation, eg. compoundClass.getSimpleName(). So that I get something like:
public interface CompoundService<T extends Compound> {
#PreAuthorize("hasRole('read_' + #root.this.compoundClass.getSimpleName())")
T getById(final Long id);
//...
}
This is basically what is mentioned here:
https://jira.springsource.org/browse/SEC-1640
however there is no example and I did not really get the solution. So should i use this? or as above #root.this?
My second question is, since this is in an interface which will be implemented by a proxy (from spring) will the experession this.compoundClass actually evaluate properly?
And last but not least how can I actually test this?*
*
I'm not actually creating a finished application but something configurable, like a framework for s specific type of database search. Meaning most authorization and authentication stuff has to come from the implementer.
Unit Testing
see http://www.lancegleason.com/blog/2009/12/07/unit-testing-spring-security-with-annotations
Since that is an old tutorial you might need to change the referenced schema versions. But more importantly the SecurityContext.xml configuration shown there does not work with Spring Security 3. See Spring Security - multiple authentication-providers for a proper configuration.
I did not require the mentioned dependencies:
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core-tiger</artifactId>
</dependency>
it worked without them (however did not create an abstract test class)
root.this
This is in fact correct approach
The problem is that you can't use getSimpleName() of a class parameter. For an in-depth discussion see http://forum.springsource.org/showthread.php?98570-Getting-Payload-Classname-in-Header-Enricher-via-SpEL
The workarounds shown there did not help me much. So I came up with this very simple solution:
Just add the string property String compoundClassSimpleName to CompoundServiceImpl and set it in the constructor (which is called by subclasses):
Public abstract class CompoundServiceImpl<T extends Compound>
implements CompoundService<T> {
private String compoundClassSimpleName;
//...
public ChemicalCompoundServiceImpl(Class<T> compoundClass) {
this.compoundClass = compoundClass;
this.compoundClassSimpleName = compoundClass.getSimpleName();
}
//...
public String getCompoundClassSimpleName(){
return compoundClassSimpleName;
}
}
and her a Service implementing above abstract service:
public class TestCompoundServiceImpl extends CompoundServiceImpl<TestCompound>
implements TestCompoundService {
//...
public TestCompoundServiceImpl() {
super(TestCompound.class);
}
//...
}
And final the #PreAuthorize annotation usage:
public interface CompoundService<T extends Compound> {
#PreAuthorize("hasRole('read_' + #root.this.getCompoundClassSimpleName())")
public T getById(final Long id);
}
For above example the expression will evaluate to a role named "read_TestCompound".
Done!
As often the solution is very simple but getting there is a PITA...
EDIT:
for completeness the test class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {
"classpath:ApplicationContext.xml",
"classpath:SecurityContext.xml"
})
public class CompoundServiceSecurityTest {
#Autowired
#Qualifier("testCompoundService")
private TestCompoundService testCompoundService;
public CompoundServiceSecurityTest() {
}
#Before
public void setUp() {
SecurityContextHolder.getContext().setAuthentication(
new UsernamePasswordAuthenticationToken("user_test", "pass1"));
}
#Test
public void testGetById() {
System.out.println("getById");
Long id = 1000L;
TestCompound expResult = new TestCompound(id, "Test Compound");
TestCompound result = testCompoundService.getById(id);
assertEquals(expResult, result);
}
}

Injecting authentication information

I have an app which connects to multiple sites with a different username/password pair for each. What I want to do is wire up dependencies so that I can say "whenever you want a FTPConnection, use this connection" and "this connection" depends on whatever the user wants.
So say I have a class like this (pseudo-Google Guice syntax):
public class FTPConnection
{
FTPConnection(#Username String username, #Password String password)...
}
And a class that uses it
public class SomeFTPSiteProcessor
{
SomeFTPSiteProcessor(#Inject FTPConnection)...
}
What I would like to do is have the "currently active" connection be created whenever I want an instance of SomeFTPSiteProcessor.
How would I do this? Would I use a scope? Would I use a provider? Help! Pseudo-code would be most appreciated.
I hope this makes some sense...
Edit: The user makes the choice of which FTP connection to use at runtime and so I need the authentication information to be provided dynamically. The language makes me think of a provider of sorts, but I can't quite wrap my head around how it would be done.
Thanks
This is the Robot Legs problem.
public class SomeFTPSiteProcessor
{
SomeFTPSiteProcessor(#JeffsFtpServer FTPConnection)...
}
public class SomeOtherFTPSiteProcessor
{
SomeFTPSiteProcessor(#FredsFtpServer FTPConnection)...
}
class FtpModule extends PrivateModule {
String username;
String password;
Class<? extends Annotation> annotation;
void configure() {
bind(String.class).annotatedWith(Username.class).with(username);
bind(String.class).annotatedWith(Password.class).with(password);
expose(FTPConnection.class).annotatedWith(annotation);
}
}
Injector injector = Injector.createInjector(
new FtpModule("fred", "password", FredsFtpServer.class),
new FtpModule("jeff", "password", JeffsFtpServer.class));
I think you would need a factory then. Likely with that factory having an instance of the injector.
class ThingieFactory() {
#Inject Injector injector;
SomeFTPSiteProcessor create(params... ) {
return injector.createChild(new Module() { set params; } ).get(SomeFTPSiteProcessor.class);
}
}

How to bind String to variable in Guice?

I'm new to Guice and here is a naive question. I learned that we could bind String to a particular value through:
bind(String.class)
.annotatedWith(Names.named("JDBC URL"))
.toInstance("jdbc:mysql://localhost/pizza");
But what if I want to bind String to any possible characters?
Or I think it could be described this way:
How can I replace "new SomeClass(String strParameter)" with Guice?
You first need to annotate the constructor for SomeClass:
class SomeClass {
#Inject
SomeClass(#Named("JDBC URL") String jdbcUrl) {
this.jdbcUrl = jdbcUrl;
}
}
I prefer to use custom annotations, like this:
class SomeClass {
#Inject
SomeClass(#JdbcUrl String jdbcUrl) {
this.jdbcUrl = jdbcUrl;
}
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.FIELD, ElementType.PARAMETER})
#BindingAnnotation
public #interface JdbcUrl {}
}
Then you need to provide a binding in your Module:
public class SomeModule extends AbstractModule {
private final String jdbcUrl; // set in constructor
protected void configure() {
bindConstant().annotatedWith(SomeClass.JdbcUrl.class).to(jdbcUrl);
}
}
Then an time Guice creates SomeClass, it will inject the parameter. For instance, if SomeOtherClass depends on SomeClass:
class SomeOtherClass {
#Inject
SomeOtherClass(SomeClass someClass) {
this.someClass = someClass;
}
Often, when you think you want to inject a String, you want to inject an object. For instance, if the String is a URL, I often inject a URI with a binding annotation.
This all assumes there is some constant value you can define at module creation time for the String. If the value isn't available at module creation time, you can use AssistedInject.
This might be off-topic, but Guice makes configuration much easier than writing an explicit binding for every String you need. You can just have a config file for them:
Properties configProps = Properties.load(getClass().getClassLoader().getResourceAsStream("myconfig.properties");
Names.bindProperties(binder(), configProps);
and voilĂ  all your config is ready for injection:
#Provides // use this to have nice creation methods in modules
public Connection getDBConnection(#Named("dbConnection") String connectionStr,
#Named("dbUser") String user,
#Named("dbPw") String pw,) {
return DriverManager.getConnection(connectionStr, user, pw);
}
Now just create your Java properties file myconfig.properties at the root of your classpath with
dbConnection = jdbc:mysql://localhost/test
dbUser = username
dbPw = password
or merge authorization information from some other source into the properties and you're set.
I was able to inject a string through Named annotation.
#Provides
#Named("stage")
String stage() {
return domain;
}
class SomeClass {
#Inject
#Named("stage")
String stageName;
}
I find a solution in the FAQ of Guice:
http://code.google.com/docreader/#p=google-guice&s=google-guice&t=FrequentlyAskedQuestions
In addition to define an annotation and a String attribute in MyModule, I need to write below line to get a instance of SomeClass:
SomeClass instance = Guice.createInjector(new MyModule("any string i like to use")).getInstance(SomeClass.class);
But I remembered that Injector.getInstance() should not be used except for the root object, so is there any better way to do this?

Resources