Permalink
Browse files

Introduced an AuthorizerInterface. A static final variable in Azzyztant

can be initialized to any type implementing this interface. Parameters
are class and method of the invocation and the InvocationMetaInfo. Use
it to implement arbitrary authorization schemes based on user,
credentials, invoked bean and invoked method.
  • Loading branch information...
advman
advman committed Aug 8, 2011
1 parent ec1677a commit cdc653071bb24068ccf8fd344bfb2508f9ee0d72

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -3,6 +3,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.io.BufferedReader;
import java.io.IOException;
@@ -17,6 +18,7 @@
import org.apache.cxf.jaxrs.client.Client;
import org.apache.cxf.jaxrs.client.JAXRSClientFactory;
+import org.apache.cxf.jaxrs.client.ServerWebApplicationException;
import org.apache.cxf.jaxrs.client.WebClient;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -43,7 +45,7 @@
*/
public class CookbookRestTest {
- private static final String BASE_URI = "http://localhost:8080/cookbookServlets/REST";
+ private static final String BASE_URI = "http://localhost:8081/cookbookServlets/REST";
private static final String FRANCE = "France";
private static final String MARSEILLES = "Marseilles";
@@ -68,6 +70,9 @@
private static Client visitClient;
private static Client zipClient;
+ private static CityFullCxfRestInterface cityProtectedSvc;
+ private static Client cityProtectedClient;
+
/**
* BEFORE CLASS: setup proxies, set their media types to APPLICATION_XML.
* There seems to be an error in Apache CXF, the REST client seemingly ignores
@@ -91,37 +96,50 @@ public static void setupProxies() {
cityClient = WebClient.client(citySvc);
cityClient.type(MediaType.APPLICATION_XML);
cityClient.accept(MediaType.MEDIA_TYPE_WILDCARD);
- // cityClient.header("X-Portal-Cred0", "REST_200_ON_ERROR");
+ cityClient.header("x-authorize-roles", "azzyzt(200-on-error=false);modify()");
+ cityClient.header("x-authenticate-userid", "junit");
countrySvc = JAXRSClientFactory.create(BASE_URI, CountryFullCxfRestInterface.class);
countryClient = WebClient.client(countrySvc);
countryClient.type(MediaType.APPLICATION_XML);
countryClient.accept(MediaType.MEDIA_TYPE_WILDCARD);
- // countryClient.header("X-Portal-Cred0", "REST_200_ON_ERROR");
+ countryClient.header("x-authorize-roles", "azzyzt(200-on-error=false);modify()");
+ countryClient.header("x-authenticate-userid", "junit");
languageSvc = JAXRSClientFactory.create(BASE_URI, LanguageFullCxfRestInterface.class);
languageClient = WebClient.client(languageSvc);
languageClient.type(MediaType.APPLICATION_XML);
languageClient.accept(MediaType.MEDIA_TYPE_WILDCARD);
- // languageClient.header("X-Portal-Cred0", "REST_200_ON_ERROR");
+ languageClient.header("x-authorize-roles", "azzyzt(200-on-error=false);modify()");
+ languageClient.header("x-authenticate-userid", "junit");
multiSvc = JAXRSClientFactory.create(BASE_URI, ModifyMultiCxfRestInterface.class);
multiClient = WebClient.client(multiSvc);
multiClient.type(MediaType.APPLICATION_XML);
multiClient.accept(MediaType.MEDIA_TYPE_WILDCARD);
- // multiClient.header("X-Portal-Cred0", "REST_200_ON_ERROR");
+ multiClient.header("x-authorize-roles", "azzyzt(200-on-error=false);modify()");
+ multiClient.header("x-authenticate-userid", "junit");
visitSvc = JAXRSClientFactory.create(BASE_URI, VisitFullCxfRestInterface.class);
visitClient = WebClient.client(visitSvc);
visitClient.type(MediaType.APPLICATION_XML);
visitClient.accept(MediaType.MEDIA_TYPE_WILDCARD);
- // visitClient.header("X-Portal-Cred0", "REST_200_ON_ERROR");
+ visitClient.header("x-authorize-roles", "azzyzt(200-on-error=false);modify()");
+ visitClient.header("x-authenticate-userid", "junit");
zipSvc = JAXRSClientFactory.create(BASE_URI, ZipFullCxfRestInterface.class);
zipClient = WebClient.client(zipSvc);
zipClient.type(MediaType.APPLICATION_XML);
zipClient.accept(MediaType.MEDIA_TYPE_WILDCARD);
- // zipClient.header("X-Portal-Cred0", "REST_200_ON_ERROR");
+ zipClient.header("x-authorize-roles", "azzyzt(200-on-error=false);modify()");
+ zipClient.header("x-authenticate-userid", "junit");
+
+ cityProtectedSvc = JAXRSClientFactory.create(BASE_URI, CityFullCxfRestInterface.class);
+ cityProtectedClient = WebClient.client(cityProtectedSvc);
+ cityProtectedClient.type(MediaType.APPLICATION_XML);
+ cityProtectedClient.accept(MediaType.MEDIA_TYPE_WILDCARD);
+ cityProtectedClient.header("x-authorize-roles", "azzyzt(200-on-error=false);");
+ cityProtectedClient.header("x-authenticate-userid", "junit");
}
@@ -404,6 +422,27 @@ public void testStoreFranceReplaceWithEgyptMakeVisit() {
assertEquals("<result>OK</result>", result);
}
+ /**
+ * TEST: Store a city with the protected client. It does not send a
+ * "modify" credential, thus the server should throw an AccessDenied Exception.
+ */
+ @Test(expected=ServerWebApplicationException.class)
+ public void testTryStoreCity() {
+ List<Dto> countries = countrySvc.list(from("META-INF/xml/get_austria.xml"));
+ assertNotNull(countries);
+ assertEquals(1, countries.size());
+ CountryDto austria = (CountryDto)countries.get(0);
+ assertEquals("Austria", austria.getName());
+
+ CityDto c = new CityDto();
+ c.setCountryId(austria.getId());
+ c.setName("Villach");
+ dump(c);
+
+ c = cityProtectedSvc.store(c);
+ fail("This should be unreachable");
+ }
+
/**
* Helper method that creates DTOs for a country and its cities
*
@@ -7,8 +7,11 @@
import org.azzyzt.jee.runtime.meta.AzzyztGeneratorCutback;
import org.azzyzt.jee.runtime.meta.AzzyztGeneratorOption;
import org.azzyzt.jee.runtime.meta.AzzyztantInterface;
+import org.azzyzt.jee.runtime.util.AuthorizationInterface;
import org.azzyzt.jee.runtime.util.StringConverterInterface;
+import com.manessinger.cookbook.util.Authorizer;
+
/**
* Generated class com.manessinger.cookbook.meta.Azzyztant
@@ -51,7 +54,19 @@
* 'convert()'. Neither should you.
*/
private final StringConverterInterface usernameConverter = null;
-
+
+ /*
+ * 'authorizer' can be set to an instance of any class that implements
+ * AuthorizationInterface.
+ *
+ * ATTENTION: keep this stateless, fast and thread-safe!!!
+ *
+ * This is actually a shared instance that, if not null, is called once
+ * upon any invocation. The runtime won't try to synchronize its call to
+ * 'checkAuthorization()'. Neither should you.
+ */
+ private final AuthorizationInterface authorizer = new Authorizer();
+
public Azzyztant() { super(); }
@@ -60,4 +75,9 @@ public StringConverterInterface getUsernameConverter() {
return usernameConverter;
}
+ @Override
+ public AuthorizationInterface getAuthorizer() {
+ return authorizer;
+ }
+
}
@@ -0,0 +1,26 @@
+package com.manessinger.cookbook.util;
+
+import java.lang.reflect.Method;
+
+import org.azzyzt.jee.runtime.exception.AccessDeniedException;
+import org.azzyzt.jee.runtime.meta.Credentials;
+import org.azzyzt.jee.runtime.meta.InvocationMetaInfo;
+import org.azzyzt.jee.runtime.util.AuthorizationInterface;
+
+public class Authorizer implements AuthorizationInterface {
+
+ @Override
+ public void checkAuthorization(
+ Class<?> clazz,
+ Method method,
+ InvocationMetaInfo mi
+ ) throws AccessDeniedException
+ {
+ Credentials credentials = mi.getCredentials();
+
+ if (!credentials.hasCredential("modify")) {
+ throw new AccessDeniedException();
+ }
+ }
+
+}
@@ -1,9 +1,12 @@
package org.azzyzt.jee.runtime.meta;
+import org.azzyzt.jee.runtime.util.AuthorizationInterface;
import org.azzyzt.jee.runtime.util.StringConverterInterface;
public interface AzzyztantInterface {
public StringConverterInterface getUsernameConverter();
+ public AuthorizationInterface getAuthorizer();
+
}
@@ -0,0 +1,13 @@
+package org.azzyzt.jee.runtime.util;
+
+import java.lang.reflect.Method;
+
+import org.azzyzt.jee.runtime.exception.AccessDeniedException;
+import org.azzyzt.jee.runtime.meta.InvocationMetaInfo;
+
+public interface AuthorizationInterface {
+
+ public void checkAuthorization(Class<?> clazz, Method method, InvocationMetaInfo mi)
+ throws AccessDeniedException;
+
+}
@@ -65,6 +65,7 @@ public MetaModel build() {
target.addMetaAnnotationInstance(new MetaAnnotationInstance(std.javaxEjbStateless, target));
target.addReferencedForeignType(std.stringConverterInterface);
+ target.addReferencedForeignType(std.authorizationInterface);
targetModel.follow(targetPackageName);
targetModel.addMetaDeclaredTypeIfTarget(target);
@@ -68,7 +68,9 @@ public MetaModel build() {
target.addReferencedForeignType(std.javaxEjbEJBTransactionRolledbackException);
target.addReferencedForeignType(std.translatableException);
target.addReferencedForeignType(std.javaxXmlWsWebServiceContext);
-
+ target.addReferencedForeignType(std.invocationMetaInfo);
+ target.addReferencedForeignType(std.authorizationInterface);
+
addGenericEaoField(target);
addEJBSessionContext(target);
addInvocationRegistryField(target);
@@ -182,6 +182,7 @@
public final MetaClass exceptionToSuccessMapper;
public final MetaClass idTranslator;
public final MetaInterface stringConverterInterface;
+ public final MetaInterface authorizationInterface;
public final MetaInterface azzyztantInterface;
public final MetaAnnotation azzyztGeneratorOptions;
public final MetaEnum azzyztGeneratorCutback;
@@ -370,6 +371,7 @@ public MetaStandardDefs() {
exceptionToSuccessMapper = MetaClass.forType(org.azzyzt.jee.runtime.service.ExceptionToSuccessMapper.class);
idTranslator = MetaClass.forType(org.azzyzt.jee.runtime.eao.IdTranslator.class);
stringConverterInterface = MetaInterface.forType(org.azzyzt.jee.runtime.util.StringConverterInterface.class);
+ authorizationInterface = MetaInterface.forType(org.azzyzt.jee.runtime.util.AuthorizationInterface.class);
azzyztantInterface = MetaInterface.forType(org.azzyzt.jee.runtime.meta.AzzyztantInterface.class);
azzyztGeneratorOptions = MetaAnnotation.forType(org.azzyzt.jee.runtime.annotation.AzzyztGeneratorOptions.class);
azzyztGeneratorCutback = MetaEnum.forType(org.azzyzt.jee.runtime.meta.AzzyztGeneratorCutback.class);
@@ -26,6 +26,18 @@ group javaAzzyztantGroup : javaGroup;
*/
private final StringConverterInterface usernameConverter = null;
+/*
+ * 'authorizer' can be set to an instance of any class that implements
+ * AuthorizationInterface.
+ *
+ * ATTENTION: keep this stateless, fast and thread-safe!!!
+ *
+ * This is actually a shared instance that, if not null, is called once
+ * upon any invocation. The runtime won't try to synchronize its call to
+ * 'checkAuthorization()'. Neither should you.
+ */
+private final AuthorizationInterface authorizer = null;
+
>>
@javaClass.extra_methods() ::= <<
@@ -34,4 +46,9 @@ public StringConverterInterface getUsernameConverter() {
return usernameConverter;
}
+@Override
+public AuthorizationInterface getAuthorizer() {
+ return authorizer;
+}
+
>>
@@ -5,8 +5,14 @@ group javaEJBInterceptorGroup : javaGroup;
@AroundInvoke
public Object aroundBeanInvocation(InvocationContext ctx) throws Exception {
- invocationRegistry.registerEJBInvocation(wsc);
+ InvocationMetaInfo mi = invocationRegistry.registerEJBInvocation(wsc);
+
try {
+
+ AuthorizationInterface authorizer = invocationRegistry.getAzzyztant().getAuthorizer();
+ if (authorizer != null) {
+ authorizer.checkAuthorization(ctx.getTarget().getClass(), ctx.getMethod(), mi);
+ }
Object result = ctx.proceed();
eao.flush();
return result;

0 comments on commit cdc6530

Please sign in to comment.