rest - Why is my spring boot stateless filter being called twice? -


i'm trying implement stateless token-based authentication on rest api i've developed using spring boot. idea client includes jwt token request, , filter extracts request, , sets securitycontext relevant authentication object based on contents of token. request routed normal, , secured using @preauthorize on mapped method.

my security config follows :

@configuration @enablewebsecurity @enableglobalmethodsecurity(prepostenabled = true) public class securityconfig extends websecurityconfigureradapter {  @autowired private jwttokenauthenticationservice authenticationservice;  @override protected void configure(httpsecurity http) throws exception {     http         .csrf().disable()         .headers().addheaderwriter(new xframeoptionsheaderwriter(xframeoptionsmode.sameorigin))         .and()         .authorizerequests()             .antmatchers("/auth/**").permitall()             .antmatchers("/api/**").authenticated()             .and()         .addfilterbefore(new statelessauthenticationfilter(authenticationservice), usernamepasswordauthenticationfilter.class); } 

with stateless filter extends genericfilterbean defined follows :

public class statelessauthenticationfilter extends genericfilterbean {      private static logger logger = logger.getlogger(statelessauthenticationfilter.class);      private jwttokenauthenticationservice authenticationservice;      public statelessauthenticationfilter(jwttokenauthenticationservice authenticationservice)     {         this.authenticationservice = authenticationservice;     }      @override     public void dofilter(   servletrequest request,                             servletresponse response,                             filterchain chain) throws ioexception, servletexception {          httpservletrequest httprequest = (httpservletrequest) request;         authentication authentication = authenticationservice.getauthentication(httprequest);         securitycontextholder.getcontext().setauthentication(authentication);          logger.info("===== security context before request =====");         logger.info("request for: " + httprequest.getrequesturi());         logger.info(securitycontextholder.getcontext().getauthentication());         logger.info("===========================================");          chain.dofilter(request, response);          securitycontextholder.getcontext().setauthentication(null);         logger.info("===== security context after request =====");         logger.info("request for: " + httprequest.getrequesturi());          logger.info(securitycontextholder.getcontext().getauthentication());         logger.info("===========================================");     }  } 

and endpoint defined :

@preauthorize("hasauthority('user')") @requestmapping (   value="/api/attachments/{attachmentid}/{filename:.+}",                     method = requestmethod.get) public responseentity<byte[]> getattacheddocumentendpoint(@pathvariable string attachmentid, @pathvariable string filename) {     logger.info("get called /attachments/" + attachmentid + "/" + filename);      // file, , return responseentity<byte[]> object } 

when doing on /api/attachments/someattachment/somefilename, including token, can see filter being invoked twice, once apparently token, , once without. restcontroller mapped request called once.

[info] [06-04-2015 12:26:44,465] [jwttokenauthenticationservice] getauthentication - getting authentication based on token supplied in http header [info] [06-04-2015 12:26:44,473] [statelessauthenticationfilter] dofilter - ===== security context before request ===== [info] [06-04-2015 12:26:44,473] [statelessauthenticationfilter] dofilter - request for: /api/attachments/1674b08b6bbd54a6efaff4a780001a9e/jpg.png [info] [06-04-2015 12:26:44,474] [statelessauthenticationfilter] dofilter - name:iser, principal:user, isauthenticated:true, grantedauthorites:[user] [info] [06-04-2015 12:26:44,474] [statelessauthenticationfilter] dofilter - =========================================== [info] [06-04-2015 12:26:44,476] [attachmentrestcontroller] getattacheddocumentendpoint - called /api/attachments/1674b08b6bbd54a6efaff4a780001a9e/jpg.png [info] [06-04-2015 12:26:44,477] [attachmentdbcontroller] getattachment - getattachment method called attachmentid:1674b08b6bbd54a6efaff4a780001a9e , , filename:jpg.png [info] [06-04-2015 12:26:44,483] [statelessauthenticationfilter] dofilter - ===== security context after request ===== [info] [06-04-2015 12:26:44,484] [statelessauthenticationfilter] dofilter - request for: /api/attachments/1674b08b6bbd54a6efaff4a780001a9e/jpg.png [info] [06-04-2015 12:26:44,484] [statelessauthenticationfilter] dofilter -  [info] [06-04-2015 12:26:44,484] [statelessauthenticationfilter] dofilter - =========================================== [info] [06-04-2015 12:26:44,507] [jwttokenauthenticationservice] getauthentication - no token supplied in http header [info] [06-04-2015 12:26:44,507] [statelessauthenticationfilter] dofilter - ===== security context before request ===== [info] [06-04-2015 12:26:44,507] [statelessauthenticationfilter] dofilter - request for: /api/attachments/1674b08b6bbd54a6efaff4a780001a9e/jpg.png [info] [06-04-2015 12:26:44,507] [statelessauthenticationfilter] dofilter -  [info] [06-04-2015 12:26:44,508] [statelessauthenticationfilter] dofilter - =========================================== [info] [06-04-2015 12:26:44,508] [statelessauthenticationfilter] dofilter - ===== security context after request ===== [info] [06-04-2015 12:26:44,508] [statelessauthenticationfilter] dofilter - request for: /api/attachments/1674b08b6bbd54a6efaff4a780001a9e/jpg.png [info] [06-04-2015 12:26:44,508] [statelessauthenticationfilter] dofilter -  [info] [06-04-2015 12:26:44,508] [statelessauthenticationfilter] dofilter - =========================================== 

what's going on here ?

edit :

it's stranger first thought - implementing simple endpoint returns simple message displays expected behaviour - it's seems when try return data responseentity above problem occur.

endpoint :

@preauthorize("hasauthority('user')") @requestmapping("/api/userhelloworld") public string userhelloworld() {     return "hello secure user world"; } 

output, showing single call filter (with debug on):

[info] [06-04-2015 19:43:25,831] [jwttokenauthenticationservice] getauthentication - getting authentication based on token supplied in http header [info] [06-04-2015 19:43:25,844] [statelessauthenticationfilter] dofilterinternal - ===== security context before request ===== [info] [06-04-2015 19:43:25,844] [statelessauthenticationfilter] dofilterinternal - request for: /api/userhelloworld [info] [06-04-2015 19:43:25,844] [statelessauthenticationfilter] dofilterinternal - response = null 200 [info] [06-04-2015 19:43:25,844] [statelessauthenticationfilter] dofilterinternal - name:user, principal:user, isauthenticated:true, grantedauthorites:[user] [info] [06-04-2015 19:43:25,845] [statelessauthenticationfilter] dofilterinternal - =========================================== [debug] [06-04-2015 19:43:25,845] [dispatcherservlet] doservice - dispatcherservlet name 'dispatcherservlet' processing request [/api/userhelloworld] [debug] [06-04-2015 19:43:25,847] [abstracthandlermethodmapping] gethandlerinternal - looking handler method path /api/userhelloworld [debug] [06-04-2015 19:43:25,848] [abstracthandlermethodmapping] gethandlerinternal - returning handler method [public java.lang.string restcontroller.userhelloworld()] [debug] [06-04-2015 19:43:25,849] [dispatcherservlet] dodispatch - last-modified value [/api/userhelloworld] is: -1 [debug] [06-04-2015 19:43:25,851] [abstractmessageconvertermethodprocessor] writewithmessageconverters - written [hello secure user world] "text/plain;charset=utf-8" using [org.springframework.http.converter.stringhttpmessageconverter@3eaf6fe7] [debug] [06-04-2015 19:43:25,852] [dispatcherservlet] processdispatchresult - null modelandview returned dispatcherservlet name 'dispatcherservlet': assuming handleradapter completed request handling [debug] [06-04-2015 19:43:25,852] [frameworkservlet] processrequest - completed request [info] [06-04-2015 19:43:25,852] [statelessauthenticationfilter] dofilterinternal - ===== security context after request ===== [info] [06-04-2015 19:43:25,853] [statelessauthenticationfilter] dofilterinternal - request for: /api/userhelloworld [info] [06-04-2015 19:43:25,853] [statelessauthenticationfilter] dofilterinternal - response = text/plain;charset=utf-8 200 [info] [06-04-2015 19:43:25,853] [statelessauthenticationfilter] dofilterinternal -  [info] [06-04-2015 19:43:25,853] [statelessauthenticationfilter] dofilterinternal - =========================================== 

okay - pretty ridiculous, seems it's issue way invoking request (via postman chrome extension)

postman seems fire in 2 requests, 1 headers, 1 without. there's open bug report describing here : https://github.com/a85/postman-chrome-extension/issues/615

the behaviour not seen if request invoked using curl, or straight browser.


Comments

Popular posts from this blog

Magento/PHP - Get phones on all members in a customer group -

php - .htaccess mod_rewrite for dynamic url which has domain names -

Website Login Issue developed in magento -