Mock Custom User in Spring Security Test -
we using spring 4.3.9.release , spring security 4.2.3.release, these of latest versions have seen. have restful (spring-mvc) backend using spring web security roles-based access api's.
we have controller looks this:
@requestmapping(value = "/create", method = requestmethod.post, produces = "application/json", headers = "content-type=application/json") public @responsebody myobjectentity createmyobject(@requestbody myobjectentity myobj) throws myobjectexception { userdetails userdetails = (userdetails) securitycontextholder.getcontext().getauthentication().getprincipal(); customuser user = null; if (userdetails instanceof customuser) { user = ((customuser) userdetails); } string email = user.getemail(); myobjectentity myobj = myobjectservice.createmyobject(myobj, email); if (securitycontextholder.getcontext().getauthentication() != null) { securitycontextholder.getcontext().setauthentication(null); } return myobj; }
we know user has logged in web-site username , password. know ui has token, , pass along in header. our security uses siteminder example, means have userdetailsservice goes third-party, passes along token, , have username, password, , roles user has. working well. did create customuserdetailsservice follows:
public class customuserdetailsservice implements userdetailsservice { @override public userdetails loaduserbyusername(string accesstoken) throws usernamenotfoundexception, preauthenticatedcredentialsnotfoundexception { // goto third-party service verify token // custom user , user roles // data, custom user } }
so, once established token valid, , have gotten additional user information third-party, , have valid role authorized api ... can execute controller itself. , see code traditional getting existing user out of spring security context.
userdetails userdetails = (userdetails) securitycontextholder.getcontext().getauthentication().getprincipal(); customuser user = null; if (userdetails instanceof customuser) { user = ((customuser) userdetails); }
actually, have read, way when have custom user , customuserdetails. code, want email of user. , works when test api advanced rest client. our qa has authenticate against web-site, , tokens passed ui, access tokens, , put in headers of advanced rest client (or postman) , works.
we have code invalidate security context when api over.
if (securitycontextholder.getcontext().getauthentication() != null) { securitycontextholder.getcontext().setauthentication(null); }
against, real api, real progress, works great. now, when comes testing, of tests work against our secured controllers , not. so, here have controller test:
@requestmapping(value = "/{productid}", method = requestmethod.get, headers = "accept=application/json") public @responsebody productentity getproductbyid(@pathvariable("productid") long productid) { logger.debug("productcontroller: getproductbyid: productid=" + productid); customuser user = authenticate(); productentity productentity = service.getbyid(productid); logger.debug("productcontroller: getproductbyid: productentity=" + productentity); invalidateuser(); return productentity; }
and here test:
@test public void testmockgetproductbyproductid() throws exception { mockhttpservletrequestbuilder requestbuilder = mockmvcrequestbuilders.get(base_url + "/1").with(user("testuser").roles("regular_user")); this.mockmvc.perform(requestbuilder).anddo(print()).andexpect(status().isok()); }
this works because when controller, don't need customeruser set, works. if role correct role ("regular_user"), works, if role not correct, 403 error expecting.
but if @ controller first posted @ top, need customuser set, , if isn't set, when try email, fail. so, have been looking @ multiple ways of setting mock user in authentication, when controller can customuser in security context.
i've done before, when using standard spring security user, , not custom user.
we can establish customuser in security context, when gets controller, , code run ....
// works userdetails userdetails = (userdetails) securitycontextholder.getcontext().getauthentication().getprincipal(); customuser user = null; // if fails because; // userdetails of instance user (spring security user) // , not customuser. if (userdetails instanceof customuser) { user = ((customuser) userdetails); }
let me add code have our customuser:
public class customuser implements userdetails { private static final long serialversionuid = -6650061185298405641l; private string username; private arraylist<grantedauthority> authorities; private string firstname; private string middlename; private string lastname; private string email; private string phone; private string externaluserid; // getters/setters // tostring }
i hope put enough information here can answer question. have spent day or 2 scouring internet can answer question no avail. of answers little older spring 3 , older spring security 3.x. if more information needed, please let me know. thanks!
i wonder ... if need customuserdetails implments userdetails?
thanks again!
this easier think.
customuser userdetails = new customuser(); /* todo: set username, authorities etc */ mockhttpservletrequestbuilder requestbuilder = mockmvcrequestbuilders.get(base_url + "/1").with(user(userdetails));
this allowed long customuser
implements userdetails
interface.
Comments
Post a Comment