Flex: BlazeDs deserialization - spring

I'm working on a webapp built using Spring + Flex. Communication between front and back uses BlazeDS and I have a custom marshaller in order to serialize data from flex to backend as:
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://localhost:8080/${context.root.cpanel}/messagebroker/amf" class="flex.messaging.endpoints.AMFEndpoint"/>
<properties>
<serialization>
<type-marshaller>es.onebox.flex.messaging.io.CustomTypeMarshaller</type-marshaller>
</serialization>
</properties>
</channel-definition>
Is there a way to configure how use a custom de-serializer from back to flex ? I need an interceptor to modify some fields of data sent from back to flex so I think this approach could work.

I've used an interceptor for Flex using:
<flex:message-interceptor ref="myMessageInterceptor"/>
And on my application.xml I've defined myMessageInterceptor as:
<bean id="myMessageInterceptor" class="es.onebox.flex.messaging.io.FlexInterceptor"/>
And this is de content of the interceptor:
public class FlexInterceptor implements ResourceHandlingMessageInterceptor
{
private static Logger logger = Logger.getLogger(FlexInterceptor.class);
public void afterCompletion(MessageProcessingContext context, Message inputMessage, Message outputMessage, Exception ex)
{
logger.info(inputMessage.getMessageId());
}
public Message postProcess(MessageProcessingContext context, Message inputMessage, Message outputMessage)
{
return outputMessage;
}
public Message preProcess(MessageProcessingContext context, Message inputMessage) {
return inputMessage;
}
}

In AMFEndpoint class [], there are fields
/**
* Returns the deserializer class name used by the endpoint.
*
* #return The deserializer class name used by the endpoint.
*/
#Override protected String getDeserializerClassName()
{
return "flex.messaging.io.amf.AmfMessageDeserializer";
}
/**
* Returns the serializer class name used by the endpoint.
*
* #return The serializer class name used by the endpoint.
*/
#Override protected String getSerializerClassName()
{
return "flex.messaging.io.amf.AmfMessageSerializer";
}
So I think you can extend the AMFendpoint and specify your own serializer/deserealizer and implement them, obviously. AmfMessageDeserializer source code is here:
http://opensource.adobe.com/svn/opensource/blazeds/branches/4.6_Apache/modules/core/src/flex/messaging/io/amf/AmfMessageDeserializer.java
Also I think if you want to change the messages sent from BlazeDS to Flex, you need to user Serializer rather than Deserializer.
Btw, downloading the whole source code for BlazeDS is pretty useful, you can add it to Eclipse and ctrl-click on classes and see the source with comments.

Related

How to validate request parameters on feign client

Is there a way to add validation to feign clients on the request parameters.
For example:
#FeignClient
public interface ZipCodeClient {
#GetMapping("/zipcodes/{zipCode}")
Optional<ZipCodeView> findByZipCode(#PathVariable("zipCode") String zipCode);
}
It would be nice to verify that zipcode is not empty and is of certain length etc, before sending the HTTP call to the server.
If your validations are simple, apply to only headers and query string parameters, you can use a RequestInterceptor for this, as it provides you the opportunity to review the RequestTemplate before it is sent to the Client.
public class ValidatingRequestInterceptor implements RequestInterceptor {
public void apply(RequestTemplate requestTemplate) {
// use the methods on the request template to check the query and values.
// throw an exception if the request is not valid.
}
}
If you need to validate the request body, you can use a custom Encoder
public class ValidatingEncoder implements Encoder {
public void encode(Object object, Type type, RequestTemplate template) {
// validate the object
// throw an exception if the request is not valid.
}
}
Lastly, if you want to validate individual parameters, you can provide a custom Expander for the parameter and validate it there. You can look at this answer for a complete explanation on how to create a custom expander that can work with Spring Cloud.
How to custom #FeignClient Expander to convert param?
For completeness, I've included an example for how to do this with vanilla Feign.
public class ZipCodeExpander implements Expander {
public String expand(Object value) {
// validate the object
// throw an exception if the request is not valid.
}
}
public interface ZipCodeClient {
#RequestLine("GET /zipcodes/{zipCode}")
Optional<ZipCodeView> findByZipCode(#Param(expander = ZipCodeExpander.class) ("zipCode") String zipCode);
}
As pointed out in this comment, a solution using the Bean Validation API would be nice. And indeed, I found in a Spring Boot project that merely placing #org.springframework.validation.annotation.Validated on the interface is sufficient for enabling Bean Validation.
So for example:
#FeignClient
#Validated
public interface ZipCodeClient {
#GetMapping("/zipcodes/{zipCode}")
Optional<ZipCodeView> findByZipCode(#PathVariable("zipCode") #NotEmpty String zipCode);
}
triggering a ConstraintViolationException in the case of violations.
Any standard Bean Validation feature should work here.
UDPATE Note that there seems to be a potential issue with this solution that might require setting a Hibernate Validator configuration property like this: hibernate.validator.allow_parallel_method_parameter_constraint=true

Validation at both Service and Controller Layer?

Is there a need to do another round of input validation, non business logic related in the service layer?
Service Layer
#Service
#Transactional
#Validated
public class AppServiceImpl implements AppService {
public App createApp(#Valid App app) { // is there a need to do #Valid here?
return appRepository.save(app);
}
}
Controller Layer
#RestController
#RequestMapping("/api")
public class AppResource {
private final AppRepository appRepository;
private final AppServiceImpl appServiceImpl;
#Autowired
public AppResource(AppRepository appRepository, AppServiceImpl appServiceImpl) {
this.appServiceImpl = appServiceImpl;
this.appRepository = appRepository;
}
/**
* POST /apps : Create a new app.
*
* #param app the app to create
* #return the ResponseEntity with status 201 (Created) and with body the new app, or with status 400 (Bad Request) if the app has already an ID
* #throws URISyntaxException if the Location URI syntax is incorrect
*/
#PostMapping("/apps")
#Timed
public ResponseEntity<App> createApp(#Valid #RequestBody App app) throws URISyntaxException {
log.debug("REST request to save App : {}", app);
if (app.getId() != null) {
return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert(ENTITY_NAME, "idexists", "A new app cannot already have an ID")).body(null);
}
App result = appServiceImpl.createApp(app);
return ResponseEntity.created(new URI("/api/apps/" + result.getId()))
.headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, result.getId().toString()))
.body(result);
}
}
Short form: Yes, you have to validate again.
From design perspective your class provides an public interface where you in general don't know who invokes the method. So for your class / method to ensure to work properly you'll have to validate the input.
If the context the class is used in is well known and you "know" that the validation is done before you may skip the additional validation. In this case you are accepting the risk that if in the future the validation is not done in the Controlling Layer or you add additional classes / use cases the invocation may fail or give unexpected results.

spring-security global-method-security protect-pointcut with #EnableGlobalMethodSecurity

How does one port from
<sec:global-method-security secured-annotations="disabled">
<sec:protect-pointcut expression='execution(* x.y.z.end*(..))' access='...' />
to spring java-config
#EnableGlobalMethodSecurity
#Configuration
public class MyConfiguration extends WebSecurityConfigurerAdapter {
?
There is a simmilar question here http://forum.spring.io/forum/spring-projects/security/726615-protect-pointcut-in-java-configuration
There's a workaround for it. The security points information is kept in MethodSecurityMetadataSource implementations (which are then used by MethodInterceptor) so we have to create an additional MethodSecurityMetadataSource. As mentioned in the spring forum post the xml pointcut configuration is kept in MapBasedMethodSecurityMetadataSource and processed by ProtectPointcutPostProcessor. we also need an instance of ProtectPointcutPostProcessor. Unfortunately this class is final and package-private so there are 2 options:
create your own class and copy/paste the whole content of the original one (that's what I did)
change the class modifiers with reflection and create an instance of the original one (haven't done that so no idea if it would work fine)
then create the following beans in your context:
#Bean
public Map<String, List<ConfigAttribute>> protectPointcutMap() {
Map<String, List<ConfigAttribute>> map = new HashMap<>();
// all the necessary rules go here
map.put("execution(* your.package.service.*Service.*(..))", SecurityConfig.createList("ROLE_A", "ROLE_B"));
return map;
}
#Bean
public MethodSecurityMetadataSource mappedMethodSecurityMetadataSource() {
// the key is not to provide the above map here. this class will be populated later by ProtectPointcutPostProcessor
return new MapBasedMethodSecurityMetadataSource();
}
// it's either the original spring bean created with reflection or your own copy of it
#Bean
public ProtectPointcutPostProcessor pointcutProcessor() {
ProtectPointcutPostProcessor pointcutProcessor = new ProtectPointcutPostProcessor((MapBasedMethodSecurityMetadataSource) mappedMethodSecurityMetadataSource());
pointcutProcessor.setPointcutMap(protectPointcutMap());
return pointcutProcessor;
}
we've created the necessary beans, now we have to tell spring to use them. I'm assuming you're extending GlobalMethodSecurityConfiguration. by default it creates DelegatingMethodSecurityMetadataSource which contains a list of other MethodSecurityMetadataSources. Depending on what you want to achieve you have following options:
if you want to keep all the other MethodSecurityMetadataSources (like the ones for parsing the #Secured annotations) you can extend the list in the delegating metadata source by overriding the following method:
#Override
protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
return mappedMethodSecurityMetadataSource();
}
it would inject it on first place in the list though which may cause some problems.
if you want to keep the other sources but want yours to be the last in the list then override the following method:
#Override
public MethodSecurityMetadataSource methodSecurityMetadataSource() {
DelegatingMethodSecurityMetadataSource metadataSource = (DelegatingMethodSecurityMetadataSource) super.methodSecurityMetadataSource();
metadataSource.getMethodSecurityMetadataSources().add(mappedMethodSecurityMetadataSource());
return metadataSource;
}
if you want your source to be the only one (you don't want to use #Secured or any other annotations) then you can override the same method, just with different content
#Override
public MethodSecurityMetadataSource methodSecurityMetadataSource() {
return mappedMethodSecurityMetadataSource();
}
that's it! I hope it will help
I followed #marhewa comments and have been able to use the Spring version of class ProtectPointcutPostProcessor by defining the following bean
/**
* Needed to use reflection because I couldn't find a way to instantiate a
* ProtectPointcutPostProcessor via a BeanFactory or ApplicationContext. This bean will process
* the AspectJ pointcut defined in the map; check all beans created by Spring; store the matches
* in the MapBasedMethodSecurityMetadataSource bean so Spring can use it during its checks
*
* #return
* #throws Exception
*/
#Bean(name = "protectPointcutPostProcessor")
Object protectPointcutPostProcessor() throws Exception {
Class<?> clazz =
Class.forName("org.springframework.security.config.method.ProtectPointcutPostProcessor");
Constructor<?> declaredConstructor =
clazz.getDeclaredConstructor(MapBasedMethodSecurityMetadataSource.class);
declaredConstructor.setAccessible(true);
Object instance = declaredConstructor.newInstance(pointcutMethodMetadataSource());
Method setPointcutMap = instance.getClass().getMethod("setPointcutMap", Map.class);
setPointcutMap.setAccessible(true);
setPointcutMap.invoke(instance, pointcuts());
return instance;
}
This way I don't need to duplicate the code of this Spring class.
Cheers

Using #ExceptionHandler or some other annotation that would work like a Spring 4.1 AsyncUncaughtExceptionHandler

I would like to configure and use a Spring 4.1 AsyncUncaughtExceptionHandler. According to the Spring team (see relevant comment here) one will be able to configure an AsyncUncaughtExceptionHandler either by with the <task:annotation-driven> or by implementing AsyncConfigurer as shown here:
#Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler() ;
}
Now my question is as follows: Is there another web-layer annotation similar to #ExceptionHandler that would work like a AsyncUncaughtExceptionHandler?
As stated in the comment, here's an approach I've taken:
It's about async data imports so all classes are called Import...
What I did not do (yet) is the uncaught exception handling, but reading your post made me think about it and it should be straight forward with Spring-AOP wrapping the Importer.process() methods. This will not be global solution but it would be adaptable for a complete application by using a more generalized Result object.
The Controller uses the ImportRequests to get processing (or done) messages. The Importer itself is not removing the results from the map but this is delegated to the controller instead (A user is clicking delete). We also have a #Scheduled task which cleans up done results after 1 hour to ensure there are not left-overs.
So here's part of the code that the Controller is able to get import results during processing:
#Service
public class ImportRequests {
private final Map<User, ImportResult> importRequests = new ConcurrentHashMap<>();
/** Add, remove, get methods for current user omitted */
}
public class ImportResult {
/** The done. */
private Future<Boolean> done;
/** The error messages. */
private List<String> messages = Collections.synchronizedList(new ArrayList<String>());;
}
#Service
public class ImportService {
#Autowired
private ImportRequests importRequests;
#Autowired
private Importer importer;
public ImportResult doImport(final ImportForm importForm) {
ImportResult result = new ImportResult();
importRequests.addImportResultForCurrentUser(result);
/* This is the actual Async call (process) */
result.setDone(importer.process(result));
return result;
}
}
#Service
public class ImporterImpl implements Importer {
/**
* doProcess will import the *big* file and update the result object with the necessary messages
*/
#Async
public Future<Boolean> process(ImportResult result) {
Boolean done = doProcess(result);
return new AsyncResult<Boolean>(done);
}
}
Hope this helps.
Original Text:
One possibility that I have used is the "#ControllerAdvice" on a class scanned by the servletcontext.
You simply create a method with the exception as a parameter and annotate that method with "#ExceptionHandler". You can even have multiple handlers for specific exception types.
The result of these methods are again handled by the DispatcherServlet, so you can render a view the same way as with request mappings.

spring security - how to configure ExpressionBasedPreInvocationAdvice to use a custom expression handler? [duplicate]

I would like to create a class that adds custom methods for use in spring security expression language for method-based authorization via annotations.
For example, I would like to create a custom method like 'customMethodReturningBoolean' to be used somehow like this:
#PreAuthorize("customMethodReturningBoolean()")
public void myMethodToSecure() {
// whatever
}
My question is this.
If it is possible, what class should I subclass to create my custom methods, how would I go about configuring it in the spring xml configuration files and come someone give me an example of a custom method used in this way?
None of the mentioned techniques will work anymore. It seems as though Spring has gone through great lengths to prevent users from overriding the SecurityExpressionRoot.
EDIT 11/19/14 Setup Spring to use security annotations:
<beans ... xmlns:sec="http://www.springframework.org/schema/security" ... >
...
<sec:global-method-security pre-post-annotations="enabled" />
Create a bean like this:
#Component("mySecurityService")
public class MySecurityService {
public boolean hasPermission(String key) {
return true;
}
}
Then do something like this in your jsp:
<sec:authorize access="#mySecurityService.hasPermission('special')">
<input type="button" value="Special Button" />
</sec:authorize>
Or annotate a method:
#PreAuthorize("#mySecurityService.hasPermission('special')")
public void doSpecialStuff() { ... }
Additionally, you may use Spring Expression Language in your #PreAuthorize annotations to access the current authentication as well as method arguments.
For example:
#Component("mySecurityService")
public class MySecurityService {
public boolean hasPermission(Authentication authentication, String foo) { ... }
}
Then update your #PreAuthorize to match the new method signature:
#PreAuthorize("#mySecurityService.hasPermission(authentication, #foo)")
public void doSpecialStuff(String foo) { ... }
You'll need to subclass two classes.
First, set a new method expression handler
<global-method-security>
<expression-handler ref="myMethodSecurityExpressionHandler"/>
</global-method-security>
myMethodSecurityExpressionHandler will be a subclass of DefaultMethodSecurityExpressionHandler which overrides createEvaluationContext(), setting a subclass of MethodSecurityExpressionRoot on the MethodSecurityEvaluationContext.
For example:
#Override
public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
MethodSecurityEvaluationContext ctx = new MethodSecurityEvaluationContext(auth, mi, parameterNameDiscoverer);
MethodSecurityExpressionRoot root = new MyMethodSecurityExpressionRoot(auth);
root.setTrustResolver(trustResolver);
root.setPermissionEvaluator(permissionEvaluator);
root.setRoleHierarchy(roleHierarchy);
ctx.setRootObject(root);
return ctx;
}
Thanks ericacm, but it does not work for a few reasons:
The properties of DefaultMethodSecurityExpressionHandler are private (reflection visibility kludges undesirable)
At least in my Eclipse, I can't resolve a MethodSecurityEvaluationContext object
The differences are that we call the existing createEvaluationContext method and then add our custom root object. Finally I just returned an StandardEvaluationContext object type since MethodSecurityEvaluationContext would not resolve in the compiler (they are both from the same interface). This is the code that I now have in production.
Make MethodSecurityExpressionHandler use our custom root:
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
// parent constructor
public CustomMethodSecurityExpressionHandler() {
super();
}
/**
* Custom override to use {#link CustomSecurityExpressionRoot}
*
* Uses a {#link MethodSecurityEvaluationContext} as the <tt>EvaluationContext</tt> implementation and
* configures it with a {#link MethodSecurityExpressionRoot} instance as the expression root object.
*/
#Override
public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
// due to private methods, call original method, then override it's root with ours
StandardEvaluationContext ctx = (StandardEvaluationContext) super.createEvaluationContext(auth, mi);
ctx.setRootObject( new CustomSecurityExpressionRoot(auth) );
return ctx;
}
}
This replaces the default root by extending SecurityExpressionRoot. Here I've renamed hasRole to hasEntitlement:
public class CustomSecurityExpressionRoot extends SecurityExpressionRoot {
// parent constructor
public CustomSecurityExpressionRoot(Authentication a) {
super(a);
}
/**
* Pass through to hasRole preserving Entitlement method naming convention
* #param expression
* #return boolean
*/
public boolean hasEntitlement(String expression) {
return hasRole(expression);
}
}
Finally update securityContext.xml (and make sure it's referenced from your applcationContext.xml):
<!-- setup method level security using annotations -->
<security:global-method-security
jsr250-annotations="disabled"
secured-annotations="disabled"
pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler"/>
</security:global-method-security>
<!--<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">-->
<bean id="expressionHandler" class="com.yourSite.security.CustomMethodSecurityExpressionHandler" />
Note: the #Secured annotation will not accept this override as it runs through a different validation handler. So, in the above xml I disabled them to prevent later confusion.

Resources