I recently upgraded to Spring Security 6, and have found that authenticating using basic auth from JS or from curl no longer works but authenticating with basic auth using Java's HttpClient does work. My goal is to be able to authenticate with all approaches.
The app uses Java 17, Spring Security 6, and Spring Session 3. It has a "login" endpoint which is just a convenience endpoint that is expected to be hit with basic auth and create a session, and it returns a User object. The session id should be used for subsequent requests to other endpoints.
The curl command is like so:
curl -kv --user admin:admin "https://localhost:9000/login"
VS the HttpClient is configured like so and calling HttpClient.get(loginUrl)
HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(300))
.cookieHandler(new CookieManager())
.authenticator(new BasicAuthenticator(username, password))
.sslContext(createSsl())
.build();
public class BasicAuthenticator extends Authenticator {
private PasswordAuthentication authentication;
public BasicAuthenticator(String username, String password) {
authentication = new PasswordAuthentication(username, password.toCharArray());
}
#Override
public PasswordAuthentication getPasswordAuthentication() {
return authentication;
}
}
The security configuration is the block below... In upgrading to SpringSecurity 6 I added the requireExplicitSave() method, I have suspicions around this because my trouble is around saving sessions, but the added code is supposed to have spring security using the old functionality.
http
.securityContext( securityContext -> securityContext.requireExplicitSave(false))
.authorizeHttpRequests((authz) -> authz
.requestMatchers(openEndpoints).permitAll()
.anyRequest().authenticated()
)
.httpBasic()
.and()
.csrf()
.disable()
.exceptionHandling()
.accessDeniedHandler((req, resp, e) -> e.printStackTrace() )
.and()
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true);
I turned on request logging, security logging, and SQL logging. The SQL is all the same, and the basic auth request is always authenticated for all scenarios. The headers are different, but I can't see the headers for the HttpClient preflight call, and of the headers I do see, I don't know why authentication or session creation would work for one set of headers but not the other.
The core of the problem seems to be that the login request from the HttpClient ends with a session being created and the request from curl does not. Note that the big difference in the server logs when using curl is "Failed to create a session, as response has been committed. Unable to store SecurityContext." However even stepping through the spring security code I can't tell what is causing the difference.
See logs here:
CURL
2022-12-14T16:38:07.594-05:00 DEBUG 92726 --- [nio-9000-exec-1] o.s.security.web.FilterChainProxy : Securing GET /login
2022-12-14T16:38:07.597-05:00 DEBUG 92726 --- [nio-9000-exec-1] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext
2022-12-14T16:38:07.704-05:00 DEBUG 92726 --- [nio-9000-exec-1] org.hibernate.SQL : select u1_0.id,u1_0.display_name,u1_0.email,u1_0.enabled,u1_0.password,u1_0.registration_time,r1_0.user_id,r1_0.role_id,u1_0.username from app_user u1_0 join user_role r1_0 on u1_0.id=r1_0.user_id where u1_0.username=?
2022-12-14T16:38:07.797-05:00 DEBUG 92726 --- [nio-9000-exec-1] o.s.s.a.dao.DaoAuthenticationProvider : Authenticated user
2022-12-14T16:38:07.799-05:00 DEBUG 92726 --- [nio-9000-exec-1] o.s.s.w.a.www.BasicAuthenticationFilter : Set SecurityContextHolder to UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=admin, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[ROLE_ADMIN, ROLE_USER]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=null], Granted Authorities=[ROLE_ADMIN, ROLE_USER]]
2022-12-14T16:38:07.801-05:00 DEBUG 92726 --- [nio-9000-exec-1] o.s.security.web.FilterChainProxy : Secured GET /login
2022-12-14T16:38:07.805-05:00 DEBUG 92726 --- [nio-9000-exec-1] o.s.w.f.CommonsRequestLoggingFilter : Before request [GET /login, headers=[host:"localhost:9000", authorization:"Basic YWRtaW46YWRtaW4=", user-agent:"curl/7.84.0", accept:"*/*"]]
2022-12-14T16:38:07.816-05:00 DEBUG 92726 --- [nio-9000-exec-1] horizationManagerBeforeMethodInterceptor : Authorizing method invocation ReflectiveMethodInvocation: public com.seebie.dto.User com.seebie.server.controller.UserController.login(java.security.Principal); target is of class [com.seebie.server.controller.UserController]
2022-12-14T16:38:07.822-05:00 DEBUG 92726 --- [nio-9000-exec-1] horizationManagerBeforeMethodInterceptor : Authorized method invocation ReflectiveMethodInvocation: public com.seebie.dto.User com.seebie.server.controller.UserController.login(java.security.Principal); target is of class [com.seebie.server.controller.UserController]
2022-12-14T16:38:07.826-05:00 DEBUG 92726 --- [nio-9000-exec-1] org.hibernate.SQL : select u1_0.id,u1_0.display_name,u1_0.email,u1_0.enabled,u1_0.password,u1_0.registration_time,u1_0.username from app_user u1_0 where u1_0.username=?
2022-12-14T16:38:07.832-05:00 DEBUG 92726 --- [nio-9000-exec-1] org.hibernate.SQL : select r1_0.user_id,r1_0.role_id from user_role r1_0 where r1_0.user_id=?
2022-12-14T16:38:07.836-05:00 DEBUG 92726 --- [nio-9000-exec-1] org.hibernate.SQL : select a1_0.user_id,a1_0.id,a1_0.city,a1_0.line1,a1_0.state,a1_0.zip from address a1_0 where a1_0.user_id=?
2022-12-14T16:38:07.840-05:00 DEBUG 92726 --- [nio-9000-exec-1] org.hibernate.SQL : select s1_0.principal_name,s1_0.primary_id,s1_0.session_id from spring_session s1_0 where s1_0.principal_name=?
2022-12-14T16:38:07.871-05:00 DEBUG 92726 --- [nio-9000-exec-1] o.s.w.f.CommonsRequestLoggingFilter : REQUEST DATA : GET /login, headers=[host:"localhost:9000", authorization:"Basic YWRtaW46YWRtaW4=", user-agent:"curl/7.84.0", accept:"*/*"]]
2022-12-14T16:38:07.873-05:00 WARN 92726 --- [nio-9000-exec-1] w.c.HttpSessionSecurityContextRepository : Failed to create a session, as response has been committed. Unable to store SecurityContext.
2022-12-14T16:38:07.873-05:00 DEBUG 92726 --- [nio-9000-exec-1] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
HttpClient
2022-12-14T06:31:28.390-05:00 DEBUG 85610 --- [o-auto-1-exec-1] o.s.security.web.FilterChainProxy : Securing GET /login
2022-12-14T06:31:28.420-05:00 DEBUG 85610 --- [o-auto-1-exec-1] s.s.w.c.SecurityContextPersistenceFilter : Set SecurityContextHolder to empty SecurityContext
2022-12-14T06:31:28.913-05:00 DEBUG 85610 --- [o-auto-1-exec-1] org.hibernate.SQL : select u1_0.id,u1_0.display_name,u1_0.email,u1_0.enabled,u1_0.password,u1_0.registration_time,r1_0.user_id,r1_0.role_id,u1_0.username from app_user u1_0 join user_role r1_0 on u1_0.id=r1_0.user_id where u1_0.username=?
2022-12-14T06:31:29.102-05:00 DEBUG 85610 --- [o-auto-1-exec-1] o.s.s.a.dao.DaoAuthenticationProvider : Authenticated user
2022-12-14T06:31:29.103-05:00 DEBUG 85610 --- [o-auto-1-exec-1] o.s.s.w.a.www.BasicAuthenticationFilter : Set SecurityContextHolder to UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=admin, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[ROLE_ADMIN, ROLE_USER]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=19ab0971-5fb3-47fd-a4f9-cdde1ad24883], Granted Authorities=[ROLE_ADMIN, ROLE_USER]]
2022-12-14T06:31:29.108-05:00 DEBUG 85610 --- [o-auto-1-exec-1] o.s.security.web.FilterChainProxy : Secured GET /login
2022-12-14T06:31:29.136-05:00 DEBUG 85610 --- [o-auto-1-exec-1] o.s.w.f.CommonsRequestLoggingFilter : Before request [GET /login, headers=[authorization:"Basic YWRtaW46YWRtaW4=", content-length:"0", host:"localhost:64723", user-agent:"Java-http-client/17.0.2", cookie:"SESSION=MTlhYjA5NzEtNWZiMy00N2ZkLWE0ZjktY2RkZTFhZDI0ODgz", Content-Type:"application/json;charset=UTF-8"]]
2022-12-14T06:31:29.274-05:00 DEBUG 85610 --- [o-auto-1-exec-1] horizationManagerBeforeMethodInterceptor : Authorizing method invocation ReflectiveMethodInvocation: public com.seebie.dto.User com.seebie.server.controller.UserController.login(java.security.Principal); target is of class [com.seebie.server.controller.UserController]
2022-12-14T06:31:29.332-05:00 DEBUG 85610 --- [o-auto-1-exec-1] horizationManagerBeforeMethodInterceptor : Authorized method invocation ReflectiveMethodInvocation: public com.seebie.dto.User com.seebie.server.controller.UserController.login(java.security.Principal); target is of class [com.seebie.server.controller.UserController]
2022-12-14T06:31:29.373-05:00 DEBUG 85610 --- [o-auto-1-exec-1] org.hibernate.SQL : select u1_0.id,u1_0.display_name,u1_0.email,u1_0.enabled,u1_0.password,u1_0.registration_time,u1_0.username from app_user u1_0 where u1_0.username=?
2022-12-14T06:31:29.392-05:00 DEBUG 85610 --- [o-auto-1-exec-1] org.hibernate.SQL : select r1_0.user_id,r1_0.role_id from user_role r1_0 where r1_0.user_id=?
2022-12-14T06:31:29.409-05:00 DEBUG 85610 --- [o-auto-1-exec-1] org.hibernate.SQL : select a1_0.user_id,a1_0.id,a1_0.city,a1_0.line1,a1_0.state,a1_0.zip from address a1_0 where a1_0.user_id=?
2022-12-14T06:31:29.413-05:00 DEBUG 85610 --- [o-auto-1-exec-1] org.hibernate.SQL : select s1_0.principal_name,s1_0.primary_id,s1_0.session_id from spring_session s1_0 where s1_0.principal_name=?
2022-12-14T06:31:29.678-05:00 DEBUG 85610 --- [o-auto-1-exec-1] o.s.w.f.CommonsRequestLoggingFilter : REQUEST DATA : GET /login, headers=[authorization:"Basic YWRtaW46YWRtaW4=", content-length:"0", host:"localhost:64723", user-agent:"Java-http-client/17.0.2", cookie:"SESSION=MTlhYjA5NzEtNWZiMy00N2ZkLWE0ZjktY2RkZTFhZDI0ODgz", Content-Type:"application/json;charset=UTF-8"]]
2022-12-14T06:31:29.680-05:00 DEBUG 85610 --- [o-auto-1-exec-1] w.c.HttpSessionSecurityContextRepository : Stored SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=admin, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[ROLE_ADMIN, ROLE_USER]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=19ab0971-5fb3-47fd-a4f9-cdde1ad24883], Granted Authorities=[ROLE_ADMIN, ROLE_USER]]] to HttpSession [org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper$HttpSessionWrapper#7ba784f2]
2022-12-14T06:31:29.680-05:00 DEBUG 85610 --- [o-auto-1-exec-1] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
Note the session in headers for the HttpClient call... I think HttpClient makes a preflight auth call that gets a 401 and then makes the "real" call with the credentials, at least that's how it was in Java 11.
I think if I understood the difference in how these calls are being made/handled that causes one technique to work but not the other, I would be able to solve the problem. So that really is the question: What is the difference in spring security 6 (along with spring session) handling session creation when using Java 17's HttpClient vs curl?
[UPDATE] to anyone who read this far: the behavior is actually expected behavior for Spring Security. A full discussion and explanation are in the spring security issue that I had opened here
Well, if we are not going to investigate why preflight requests make sense (IMO, that seems to be a bug), the explanation of what has been changed in spring 6 is following:
as was mentioned in Session Management Migrations now Spring does not enable SecurityContextPersistenceFilter by default, however in Spring 5 SecurityContextPersistenceFilter was responsible for saving SecurityContext in http session (and hence creating it) unless that was explicitly disabled. Now in order to return previous behaviour you desire you need to setup SecurityContextRepository via:
http.securityContext(securityContext -> securityContext.
securityContextRepository(new HttpSessionSecurityContextRepository())
)
im trying to to read a value from Google-Cloud storage from my Spring application. I use the Spring Cloud GCP extension to work with Google Cloud Storage.
My Pom.xml for the gcp dependency:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gcp-starter-storage</artifactId>
<version>1.1.2.RELEASE</version>
</dependency>
When i try to read a file from my rest-endpoint i get the exception(at the end of my answer) that somehow that my token could not be refreshed ? Where i can set my clientId or is there something else going on ? I used the code from the sample application which is provided by pivotal and google.
#RestController
public class GCloudStorageController {
#Value("gs://test_files_test/test.txt")
private Resource gcsFile;
#RequestMapping(value = "/cloud", method = RequestMethod.GET)
public String readGcsFile() throws IOException {
return StreamUtils.copyToString(
this.gcsFile.getInputStream(),
Charset.defaultCharset()) + "\n";
}
#RequestMapping(value = "/cloud", method = RequestMethod.POST)
String writeGcs(#RequestBody String data) throws IOException {
try (OutputStream os = ((WritableResource) this.gcsFile).getOutputStream()) {
os.write(data.getBytes());
}
return "file was updated\n";
}
}
2019-08-20 20:27:02.555 DEBUG 12348 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Failed to complete request: com.google.cloud.storage.StorageException: 400 Bad Request
{
"error": "invalid_grant",
"error_description": "Bad Request"
}
2019-08-20 20:27:02.556 DEBUG 12348 --- [nio-8080-exec-1] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher#24f1dc0f
2019-08-20 20:27:02.557 DEBUG 12348 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2019-08-20 20:27:02.557 DEBUG 12348 --- [nio-8080-exec-1] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2019-08-20 20:27:02.563 ERROR 12348 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is com.google.cloud.storage.StorageException: 400 Bad Request
{
"error": "invalid_grant",
"error_description": "Bad Request"
}] with root cause
com.google.api.client.http.HttpResponseException: 400 Bad Request
{
"error": "invalid_grant",
"error_description": "Bad Request"
}
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1094) ~[google-http-client-1.30.1.jar:na]
at com.google.auth.oauth2.UserCredentials.refreshAccessToken(UserCredentials.java:193) ~[google-auth-library-oauth2-http-0.16.1.jar:na]
at com.google.auth.oauth2.OAuth2Credentials.refresh(OAuth2Credentials.java:165) ~[google-auth-library-oauth2-http-0.16.1.jar:na]
at com.google.auth.oauth2.OAuth2Credentials.getRequestMetadata(OAuth2Credentials.java:151) ~[google-auth-library-oauth2-http-0.16.1.jar:na]
at com.google.auth.http.HttpCredentialsAdapter.initialize(HttpCredentialsAdapter.java:96) ~[google-auth-library-oauth2-http-0.16.1.jar:na]
at com.google.cloud.http.HttpTransportOptions$1.initialize(HttpTransportOptions.java:159) ~[google-cloud-core-http-1.79.0.jar:1.79.0]
at com.google.cloud.http.CensusHttpModule$CensusHttpRequestInitializer.initialize(CensusHttpModule.java:109) ~[google-cloud-core-http-1.79.0.jar:1.79.0]
at com.google.api.client.http.HttpRequestFactory.buildRequest(HttpRequestFactory.java:88) ~[google-http-client-1.30.1.jar:na]
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.buildHttpRequest(AbstractGoogleClientRequest.java:430) ~[google-api-client-1.30.1.jar:1.30.1]
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:549) ~[google-api-client-1.30.1.jar:1.30.1]
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:482) ~[google-api-client-1.30.1.jar:1.30.1]
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:599) ~[google-api-client-1.30.1.jar:1.30.1]
at com.google.cloud.storage.spi.v1.HttpStorageRpc.get(HttpStorageRpc.java:433) ~[google-cloud-storage-1.79.0.jar:1.79.0]
at com.google.cloud.storage.StorageImpl$5.call(StorageImpl.java:240) ~[google-cloud-storage-1.79.0.jar:1.79.0]
at com.google.cloud.storage.StorageImpl$5.call(StorageImpl.java:237) ~[google-cloud-storage-1.79.0.jar:1.79.0]
at com.google.api.gax.retrying.DirectRetryingExecutor.submit(DirectRetryingExecutor.java:105) ~[gax-1.46.1.jar:1.46.1]
at com.google.cloud.RetryHelper.run(RetryHelper.java:76) ~[google-cloud-core-1.79.0.jar:1.79.0]
at com.google.cloud.RetryHelper.runWithRetries(RetryHelper.java:50) ~[google-cloud-core-1.79.0.jar:1.79.0]
at com.google.cloud.storage.StorageImpl.get(StorageImpl.java:236) ~[google-cloud-storage-1.79.0.jar:1.79.0]
at com.google.cloud.storage.StorageImpl.get(StorageImpl.java:254) ~[google-cloud-storage-1.79.0.jar:1.79.0]
at org.springframework.cloud.gcp.storage.GoogleStorageResource.getBlob(GoogleStorageResource.java:165) ~[spring-cloud-gcp-storage-1.1.2.RELEASE.jar:1.1.2.RELEASE]
at
Thank you Joe. The resource to implement 'Spring Cloud GCP Core' was never mentioned in the tutorials or i overlooked it.
Somehow another account was connected in my Google Cloud SDK on my console. So i used
gcloud auth application-default login
and logged in the right account. Now it works. Thank you.
This looks like an issue regarding authentication. Did you follow the generic 'Spring Cloud GCP Core' [1] configuration?
Check your application.properties [2] (or other configuration) and make sure it contains at least the following properties:
spring.cloud.gcp.datastore.project-id=XXX
spring.cloud.gcp.datastore.credentials.location=YYY
or choose an other method shown in [1].
[1] https://cloud.spring.io/spring-cloud-static/spring-cloud-gcp/1.1.2.RELEASE/single/spring-cloud-gcp.html#spring-cloud-gcp-core
[2] https://github.com/spring-cloud/spring-cloud-gcp/blob/master/spring-cloud-gcp-samples/spring-cloud-gcp-data-datastore-sample/src/main/resources/application.properties
Faced spring integration java-dsl issue, I'm stuck. This is a code I have for my flow declaration:
#Bean
public IntegrationFlow orchestrationFlow() {
return IntegrationFlows.from(
Jms.messageDrivenChannelAdapter(queueConnectionFactory())
.destination(bookingQueue())
.outputChannel(bookingChannel()))
.<String, BookingRequest>transform(s -> {
Ticket t = new Gson().fromJson(s, Ticket.class);
return new BookingRequest()
.setMovieId(t.getMovie().getId())
.setRow(t.getSeat().getRow())
.setSeat(t.getSeat().getNumber())
.setScreenNumber(t.getScreenNumber()
);
})
// HTTP part goes here
.<BookingRequest, HttpEntity>transform(HttpEntity::new)
.handle(
Http.outboundChannelAdapter(bookingServerUrl)
.httpMethod(HttpMethod.POST)
.extractPayload(true)
.expectedResponseType(BookStatus.class)
)
// and here HTTP part ends
.handle(
Jms.outboundAdapter(responseDestinationTemplate())
)
.get();
}
And everything was OK until I utilized HTTP outbound channel adapter. I need to call simple RESTful interface and code above does it pretty well. But, following Jms.outboundAdapter(responseDestinationTemplate()) line leads to nothing, no action performes after successfull http call.
If I remove http flow part (surrounded by comments) - it works. Implemented so much stuff, almost understood and saw beauty and simplicity of integration ...aand this is it. Yet another place I got stuck in.
And here are log after success REST call:
2016-02-08 21:01:22.155 DEBUG 18209 --- [enerContainer-1] o.s.web.client.RestTemplate : POST request for "http://localhost:9052/api/book" resulted in 200 (OK)
2016-02-08 21:01:22.156 DEBUG 18209 --- [enerContainer-1] o.s.web.client.RestTemplate : Reading [class c.e.m.integration.domain.BookStatus] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter#6b9469bd]
2016-02-08 21:01:22.168 DEBUG 18209 --- [enerContainer-1] i.h.o.HttpRequestExecutingMessageHandler : handler 'org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler#0' produced no reply for request Message: GenericMessage [payload=<BookingRequest(movieId=0, row=1, seat=1, screenNumber=1),{}>, headers={jms_redelivered=false, jms_replyTo=queue://statusChannel, jms_correlationId=5021291a-d4d5-47ca-b591-b6f311378688, correlationId=1d41f05a-3695-4adb-87b0-d75c17bbc3ad, id=a1fb2a2f-5d78-3183-d409-3f60aae74a20, priority=4, jms_timestamp=1454950877264, jms_messageId=ID:ins-laptop-31198-1454948247657-1:9:1:1:1, timestamp=1454950877352}]
2016-02-08 21:01:22.168 DEBUG 18209 --- [enerContainer-1] o.s.integration.channel.DirectChannel : postSend (sent=true) on channel 'inboundFlow.channel#2', message: GenericMessage [payload=<BookingRequest(movieId=0, row=1, seat=1, screenNumber=1),{}>, headers={jms_redelivered=false, jms_replyTo=queue://statusChannel, jms_correlationId=5021291a-d4d5-47ca-b591-b6f311378688, correlationId=1d41f05a-3695-4adb-87b0-d75c17bbc3ad, id=a1fb2a2f-5d78-3183-d409-3f60aae74a20, priority=4, jms_timestamp=1454950877264, jms_messageId=ID:ins-laptop-31198-1454948247657-1:9:1:1:1, timestamp=1454950877352}]
2016-02-08 21:01:22.168 DEBUG 18209 --- [enerContainer-1] o.s.integration.channel.DirectChannel : postSend (sent=true) on channel 'inboundFlow.channel#1', message: GenericMessage [payload=BookingRequest(movieId=0, row=1, seat=1, screenNumber=1), headers={jms_redelivered=false, jms_replyTo=queue://statusChannel, jms_correlationId=5021291a-d4d5-47ca-b591-b6f311378688, correlationId=1d41f05a-3695-4adb-87b0-d75c17bbc3ad, id=859af23d-214f-4400-e9cb-7d40308755cd, priority=4, jms_timestamp=1454950877264, jms_messageId=ID:ins-laptop-31198-1454948247657-1:9:1:1:1, timestamp=1454950877350}]
2016-02-08 21:01:22.168 DEBUG 18209 --- [enerContainer-1] o.s.integration.channel.DirectChannel : postSend (sent=true) on channel 'inboundFlow.channel#0', message: GenericMessage [payload={"screenNumber":1,"seat":{"row":1,"number":1},"movie":{"id":0,"name":"The Matrix"}}, headers={jms_redelivered=false, jms_replyTo=queue://statusChannel, jms_correlationId=5021291a-d4d5-47ca-b591-b6f311378688, correlationId=1d41f05a-3695-4adb-87b0-d75c17bbc3ad, id=636638ed-aec2-082e-6181-0484999fd807, priority=4, jms_timestamp=1454950877264, jms_messageId=ID:ins-laptop-31198-1454948247657-1:9:1:1:1, timestamp=1454950877331}]
No errors, no warnings at all.
Spring Integration provides two MessageHandler types: one-way - just handle message and stop. And another one is like: handle request message and produce reply to the output channel.
The first one is called like outboundChannelAdapter and with your HTTP case you just only send a POST request and don't worry about the reply.
Since the message flow is stopped on the outboundChannelAdapter no any further action is possible in the integration chain. Like in your case the next Jms.outboundAdapter won't be reached.
If you really expect the reply from your REST service you should use Http.outboundGateway instead. And your BookStatus will be sent to the JMS as you'd like by your last .handle() in the flow.
i want to use spring and oauth and so far it seemed to work.
now i added a zuul proxy that is configured like that:
spring:
oauth2:
sso:
home:
secure: false
path: /,/**/*.html
client:
accessTokenUri: http://${authserver.hostname}:${authserver.port}/${authserver.contextPath}/oauth/token
userAuthorizationUri: http://${authserver.hostname}:${authserver.port}/${authserver.contextPath}/oauth/authorize
clientId: webapp
clientSecret: secret
resource:
id: apis
userInfoUri: http://${authserver.hostname}:${authserver.port}/${authserver.contextPath}/rest/me
preferTokenInfo: false
whenever i try to access an resource server it tries to verify my authentication but my authserver endpoint seems to return text/html instead of json.
Created GET request for "http://localhost:8091/userauth/rest/me"
2015-11-24 14:07:12.275 DEBUG 3601 --- [nio-8080-exec-3] o.s.s.oauth2.client.OAuth2RestTemplate : Setting request Accept header to [application/json, application/*+json]
2015-11-24 14:07:12.287 DEBUG 3601 --- [nio-8080-exec-3] o.s.s.oauth2.client.OAuth2RestTemplate : GET request for "http://localhost:8091/userauth/rest/me" resulted in 200 (OK)
2015-11-24 14:07:12.288 INFO 3601 --- [nio-8080-exec-3] o.s.c.s.o.r.UserInfoTokenServices : Could not fetch user details: class org.springframework.web.client.RestClientException, Could not extract response: no suitable HttpMessageConverter found for response type [interface java.util.Map] and content type [text/html;charset=UTF-8]
i already forced json and when accessing auth server directly via curl i get json formatted principal.
#RequestMapping(value="/me", produces = "application/json")
public Principal getCurrentLoggedinUser(Principal user){
return user;
}
any ideas how to send json to my zuul proxy so it can verify my authentication?
Testing some issues with an application that has been created using the Web-Harvest library to no avail. Our network environment has a mix of proxies and other filters and I am trying to rule out a problematic User-Agent string.
I think the issue is with how the string is being specified in the application, but I don't know how to output the supplied string for debugging.
I can see the string within the IDE debugger, but I really need this to have this output for others to test on the server.
You can output the headers (and other information about the http processor) by querying the http object after it is executed.
Below is an example code which saves header information into a webharvest variable
<config>
<http url="${yoururl}"></http>
<script><![CDATA[
String keys="";
for(int i=0;i<http.headers.length;i++) {
keys+=(http.headers[i].key + "=" + http.headers[i].value +"\n---\n");
}
SetContextVar("myCookie", keys);
]]>
</script>
</config>
the myCookie variable then returns something like:
Server=Apache
---
Content-Language=en-GB
---
Pragma=no-cache
---
Cache-Control=no-cache,no-store,must-revalidate
---
Expires=0
---
Content-Type=text/html;charset=UTF-8
---
Date=Thu, 17 Jul 2014 14:35:41 GMT
---
Transfer-Encoding=chunked
---
Connection=keep-alive
---
Connection=Transfer-Encoding
---
Set-Cookie=Unique=%1%enc%3~~~ Domain=~~~; Path=/; Expires=Sat, 16 Jul 2016 14:35:40 GMT; HttpOnly
---
Set-Cookie=Session=%1%V2ID~~~
---
Set-Cookie=ServerPool=A; Domain=~~~
---
Set-Cookie=005db%3Bhac01a%3A10023%3B;
---
Set-Cookie=ReturnTo=%1%%2F~~~
---