java - Inject SecurityContext info and Request Body into @BeanParam -


currently i'm rendering command object in messagebodyreader i'd able in @beanparam:

  1. inject field derived securitycontext (is there somewhere hook in conversion?).

  2. have field inject has been materialised messagebodyreader.

is possible ?

note: go down update. guess is possible use @beanparam. though need inject securitycontext bean , extract name info.


there's no way achieve @beanparam corrected. could use messagebodyreader way doing, imo that's more of hack anything. instead, way achieve use framework components way supposed used, involves custom parameter injection.

to achieve this, need 2 things, valuefactoryprovider provide parameter values, , injectionresolver own custom annotation. won't explaining example below, can find explanation in

you can run below example junit test. included 1 class. these dependencies used.

<dependency>     <groupid>org.glassfish.jersey.test-framework.providers</groupid>     <artifactid>jersey-test-framework-provider-grizzly2</artifactid>     <version>2.19</version>     <scope>test</scope> </dependency> <dependency>     <groupid>org.glassfish.jersey.media</groupid>     <artifactid>jersey-media-json-jackson</artifactid>     <version>2.19</version>     <scope>test</scope> </dependency> 

and here test

import java.io.ioexception; import java.lang.annotation.elementtype; import java.lang.annotation.retention; import java.lang.annotation.retentionpolicy; import java.lang.annotation.target; import java.security.principal; import javax.inject.inject; import javax.inject.singleton; import javax.ws.rs.consumes; import javax.ws.rs.post; import javax.ws.rs.path; import javax.ws.rs.produces; import javax.ws.rs.client.entity; import javax.ws.rs.container.containerrequestcontext; import javax.ws.rs.container.containerrequestfilter; import javax.ws.rs.container.prematching; import javax.ws.rs.core.mediatype; import javax.ws.rs.core.response; import javax.ws.rs.core.securitycontext; import org.glassfish.hk2.api.factory; import org.glassfish.hk2.api.injectionresolver; import org.glassfish.hk2.api.servicelocator; import org.glassfish.hk2.api.typeliteral; import org.glassfish.hk2.utilities.binding.abstractbinder; import org.glassfish.jersey.server.containerrequest; import org.glassfish.jersey.server.resourceconfig; import org.glassfish.jersey.server.internal.inject.abstractcontainerrequestvaluefactory; import org.glassfish.jersey.server.internal.inject.abstractvaluefactoryprovider; import org.glassfish.jersey.server.internal.inject.multivaluedparameterextractorprovider; import org.glassfish.jersey.server.internal.inject.paraminjectionresolver; import org.glassfish.jersey.server.model.parameter; import org.glassfish.jersey.server.spi.internal.valuefactoryprovider; import org.glassfish.jersey.test.jerseytest; import static org.junit.assert.assertequals; import org.junit.test;  public class custominjectiontest extends jerseytest {      @target(elementtype.parameter)     @retention(retentionpolicy.runtime)     public static @interface customparam {     }      public static class custommodel {          public string name;         public requestbody body;     }      public static class requestbody {          public string message;     }      public static class customparamvaluefactory             extends abstractcontainerrequestvaluefactory<custommodel> {          @override         public custommodel provide() {             containerrequest request = getcontainerrequest();             string name = request.getsecuritycontext().getuserprincipal().getname();             requestbody body = request.readentity(requestbody.class);             custommodel model = new custommodel();             model.body = body;             model.name = name;             return model;         }     }      public static class customvaluefactoryprovider extends abstractvaluefactoryprovider {          @inject         public customvaluefactoryprovider(multivaluedparameterextractorprovider multiprovider,                                           servicelocator locator) {             super(multiprovider, locator, parameter.source.unknown);         }          @override         protected factory<?> createvaluefactory(parameter parameter) {             if (custommodel.class == parameter.gettype()                     && parameter.isannotationpresent(customparam.class)) {                 return new customparamvaluefactory();             }             return null;         }       }      public static class customparaminjectionresolver extends paraminjectionresolver<customparam> {          public customparaminjectionresolver() {             super(customvaluefactoryprovider.class);         }     }      private static class custominjectbinder extends abstractbinder {          @override         protected void configure() {             bind(customvaluefactoryprovider.class)                     .to(valuefactoryprovider.class)                     .in(singleton.class);             bind(customparaminjectionresolver.class)                     .to(new typeliteral<injectionresolver<customparam>>(){})                     .in(singleton.class);         }      }      private static final string principal_name = "peeskillet";      @prematching     public static class securitycontextfilter implements containerrequestfilter {          @override         public void filter(containerrequestcontext requestcontext) throws ioexception {             requestcontext.setsecuritycontext(new securitycontext(){                 public principal getuserprincipal() {                     return new principal() {                          public string getname() { return principal_name; }                     };                 }                 public boolean isuserinrole(string role) { return false; }                 public boolean issecure() { return true;}                 public string getauthenticationscheme() { return null; }             });            }       }      @path("test")     public static class testresource {         @post         @produces(mediatype.text_plain)         @consumes(mediatype.application_json)         public string post(@customparam custommodel model) {             return model.name + ":" + model.body.message;         }     }      @override     public resourceconfig configure() {         return new resourceconfig(testresource.class)                 .register(securitycontextfilter.class)                 .register(new custominjectbinder());     }      @test     public void should_return_name_with_body() {         requestbody body = new requestbody();         body.message = "hello world";         response response = target("test").request()                 .post(entity.json(body));         assertequals(200, response.getstatus());         string responsebody = response.readentity(string.class);         assertequals(principal_name + ":" + body.message, responsebody);         system.out.println(responsebody);     } } 

note read request body containerrequest inside customparamvaluefactory. same requestbody sent in json request in @test.


update

so surprise, is possible use @beanparam. here following bean used test

public static class custommodel {      @context     public securitycontext securitycontext;     public requestbody body; }  public static class requestbody {      public string message; } 

the difference previous test instead of name securitycontext.principal, need inject entire securitycontext. there's no way inject name principal, manually.

the thing surprised me though, able inject requestbody entity. didn't know possible.

here complete test

import java.io.ioexception; import java.security.principal; import javax.ws.rs.beanparam; import javax.ws.rs.consumes; import javax.ws.rs.post; import javax.ws.rs.path; import javax.ws.rs.produces; import javax.ws.rs.client.entity; import javax.ws.rs.container.containerrequestcontext; import javax.ws.rs.container.containerrequestfilter; import javax.ws.rs.container.prematching; import javax.ws.rs.core.context; import javax.ws.rs.core.mediatype; import javax.ws.rs.core.response; import javax.ws.rs.core.securitycontext; import org.glassfish.jersey.server.resourceconfig; import org.glassfish.jersey.test.jerseytest; import static org.junit.assert.assertequals; import org.junit.test;  public class custominjecttesttake2 extends jerseytest {      private static final string principal_name = "peeskillet";     private static final string message = "hello world";     private static final string response = principal_name + ":" + message;      public static class custommodel {          @context         public securitycontext securitycontext;         public requestbody body;     }      public static class requestbody {          public string message;     }      @prematching     public static class securitycontextfilter implements containerrequestfilter {          @override         public void filter(containerrequestcontext requestcontext) throws ioexception {             requestcontext.setsecuritycontext(new securitycontext(){                 public principal getuserprincipal() {                     return new principal() {                          public string getname() { return principal_name; }                     };                 }                 public boolean isuserinrole(string role) { return false; }                 public boolean issecure() { return true;}                 public string getauthenticationscheme() { return null; }             });            }       }      @path("test")     public static class testresource {         @post         @produces(mediatype.text_plain)         @consumes(mediatype.application_json)         public string post(@beanparam custommodel model) {             return model.securitycontext.getuserprincipal().getname()                      + ":"  + model.body.message;         }     }      @override     public resourceconfig configure() {         return new resourceconfig(testresource.class)                 .register(securitycontextfilter.class);     }      @test     public void should_return_name_with_body() {         requestbody body = new requestbody();         body.message = "hello world";         response response = target("test").request()                 .post(entity.json(body));         assertequals(200, response.getstatus());         string responsebody = response.readentity(string.class);         assertequals(response, responsebody);         system.out.println(responsebody);     } } 

see also:


Comments

Popular posts from this blog

javascript - Chart.js (Radar Chart) different scaleLineColor for each scaleLine -

apache - Error with PHP mail(): Multiple or malformed newlines found in additional_header -

java - Android – MapFragment overlay button shadow, just like MyLocation button -