java - Jersey client using an authenticated session -
in given moment in time authenticated session created.
i need create jersey client (post method) using authenticated session.
i've tried set jsessionid in jersey client doesn't recognize session.
client client = client.create(); final string url = "http://localhost:8080/api/send"; webresource wr = client.resource(url); javax.ws.rs.core.cookie cookie=new javax.ws.rs.core.cookie("jsessionid", "521448844j5we54d"); wr.cookie(cookie); // set post parameters formdatamultipart multipart = new formdatamultipart(); formdatabodypart fdp = new formdatabodypart("file", uploadedinputstream, mediatype.multipart_form_data_type); multipart.bodypart(fdp); string response = wr.type(mediatype.multipart_form_data_type).post(string.class, multipart); system.out.println(response);
i've tried code below, in jersey client call first api authenticate session , try use same client object call api require auth session, didn't work.
client client = client.create(); final string url = "http://localhost:8080/api/auth"; webresource wr = client.resource(url); //set parametes request multivaluedmap<string, string> queryparams = new multivaluedmapimpl(); queryparams.add("user", "admin"); queryparams.add("pass", "123456"); wr.queryparams(queryparams); clientresponse response = wr.type(mediatype.multipart_form_data_type).post(clientresponse.class); system.out.println(response.getcookies().tostring()); //------------------------------------------------------------ final string url2 = "http://localhost:8080/api/send"; webresource wr2 = client.resource(url2); // set post parameters formdatamultipart multipart = new formdatamultipart(); formdatabodypart fdp = new formdatabodypart("file", uploadedinputstream, mediatype.multipart_form_data_type); multipart.bodypart(fdp); string response2 = wr2.type(mediatype.multipart_form_data_type).post(string.class, multipart); system.out.println(response2);
how can ? mean, how use authenticated jsessionid in new jersey client connection ?
regards.
i think best way use jwt user authorization.
i assuming have authenticated user via api endpoint. once user authenticated, can reply header element. can read more jwt @ https://jwt.io/introduction/
your implementation should following steps.
1) authenticate user , upon successful authentication, add "authorization: " token response.
2) in every api call, expect user pass authorization header each request , use filter authorize user parsing jwt token. may want @inject parser , make sure parser threadsafe.
3-a) if jwt token valid, let request pass through resource.
3-b) if jwt token invalid, reply wit http 401.
here sample implementation.
import com.google.inject.inject; import com.nimbusds.jose.joseexception; import com.nimbusds.jose.proc.badjoseexception; import com.nimbusds.jose.proc.securitycontext; import com.nimbusds.jwt.jwt; import com.nimbusds.jwt.jwtclaimsset; import com.nimbusds.jwt.jwtparser; import com.nimbusds.jwt.proc.configurablejwtprocessor; import org.slf4j.logger; import org.slf4j.loggerfactory; import javax.annotation.priority; import javax.ws.rs.priorities; import javax.ws.rs.webapplicationexception; import javax.ws.rs.container.containerrequestcontext; import javax.ws.rs.container.containerrequestfilter; import javax.ws.rs.container.prematching; import javax.ws.rs.core.multivaluedmap; import javax.ws.rs.core.response; import javax.ws.rs.ext.provider; import java.io.ioexception; import java.text.parseexception; @prematching @priority(priorities.authentication) @provider @secured public class simpleauthorizationfilter implements containerrequestfilter { static jwtparser jwtparser = null; private static final logger logger = loggerfactory.getlogger(simpleauthorizationfilter.class); @inject private configurablejwtprocessor jwtprocessor; public simpleauthorizationfilter() { logger.debug("init {}", getclass().getname()); } @override public void filter(containerrequestcontext requestcontext) throws ioexception { if (logger.isdebugenabled()) { logger.debug("began authorization filter {}", requestcontext.geturiinfo().getpath()); } multivaluedmap < string, string > headers = requestcontext.getheaders(); jwt jwt = null; if (headers.containskey(accesstokens.authorization)) { string accesstoken = headers.getfirst(accesstokens.authorization); try { jwt = jwtparser.parse(accesstoken); } catch (parseexception parseexception) { logger.error("unable parse jwt token {}, reason {}", requestcontext.geturiinfo().getpath(), parseexception.getmessage()); throw new webapplicationexception("unable parse jwt token", response.status.unauthorized); } // check if jwt has been init successfully. if (jwt == null) { logger.error("jwt null {}", requestcontext.geturiinfo().getpath()); throw new webapplicationexception("unable init jwt", response.status.unauthorized); } try { if (jwt.getjwtclaimsset().getexpirationtime().before(new java.util.date())) { logger.debug("jwt token expired on {}, requesting new token ", jwt.getjwtclaimsset().getexpirationtime().tostring()); } else { // nothing, continue usual. } } catch (parseexception e) { logger.error("authorization failed @ {} , due {}", requestcontext.geturiinfo().getpath(), e.getmessage()); throw new webapplicationexception("unable authorize " + e.getmessage(), response.status.unauthorized); } securitycontext ctx = null; // optional context parameter, not required here jwtclaimsset claimsset = null; try { claimsset = jwtprocessor.process(accesstoken, ctx); } catch (parseexception e) { logger.error("authorization failed @ parseexception {} , due {}", requestcontext.geturiinfo().getpath(), e.getmessage()); throw new webapplicationexception("unable authorize " + e.getmessage(), response.status.unauthorized); } catch (badjoseexception e) { logger.error("authorization failed @ badjoseexception {} , due {}", requestcontext.geturiinfo().getpath(), e.getmessage()); throw new webapplicationexception("unable authorize " + e.getmessage(), response.status.unauthorized); } catch (joseexception e) { logger.error("authorization failed @ joseexception {} , due {}", requestcontext.geturiinfo().getpath(), e.getmessage()); throw new webapplicationexception("unable authorize " + e.getmessage(), response.status.unauthorized); } // should not have happened. if (claimsset == null) { logger.error("jwt claim null failed @ {} , due {}", requestcontext.geturiinfo().getpath()); throw new webapplicationexception("unable authorize", response.status.unauthorized); } } else { logger.error("authorization header missing {}", requestcontext.geturiinfo().getpath()); throw new webapplicationexception("authorization header missing", response.status.unauthorized); } } }
i created annotation @secured
, resource method annotated @secured
greeted first filter.
here annotation:
import javax.ws.rs.namebinding; import java.lang.annotation.retention; import java.lang.annotation.target; import static java.lang.annotation.elementtype.method; import static java.lang.annotation.elementtype.type; import static java.lang.annotation.retentionpolicy.runtime; @namebinding @retention(runtime) @target({type, method}) public @interface secured { }
then created dynamicfeature as:
import org.slf4j.logger; import org.slf4j.loggerfactory; import javax.ws.rs.container.dynamicfeature; import javax.ws.rs.container.resourceinfo; import javax.ws.rs.core.featurecontext; import javax.ws.rs.ext.provider; @provider public class resourcefilterbindingfeature implements dynamicfeature { private static final logger logger = loggerfactory.getlogger(resourcefilterbindingfeature.class); @override public void configure(resourceinfo resourceinfo, featurecontext context) { if (resourceinfo.getresourcemethod().isannotationpresent(secured.class)) { logger.info("{} annotated secure method " , resourceinfo.getresourcemethod().getname() ); context.register(customauthorizationfilter.class); } } }
you need register above dyamicfeature in jersey as
register(simpleauthorizationfilter.class)
finally, here resource used test
import javax.annotation.security.rolesallowed; import javax.ws.rs.consumes; import javax.ws.rs.get; import javax.ws.rs.path; import javax.ws.rs.produces; import javax.ws.rs.core.mediatype; import javax.ws.rs.core.response; @path("/authorizationtest") @consumes({mediatype.application_json}) @produces({mediatype.application_json}) public class authorizationtest { @get @path("/secure") @secured public response secure(){ return response.ok(mediatype.application_json).build(); } @get @path("/unsecure") public response unsecure(){ return response.ok(mediatype.application_json).build(); } }
hope helps.
Comments
Post a Comment