When i perform a request using HTTP POST method from Angular, response comes without set-cookie header, contrary when I perform a request using HTTP GET method response comes with set-cookie Header.
I know that when POST method is used a preflight OPTIONS request is automatically issued by a browser. I am looking for advice what can i make so after POST method request client get set-cookie header as it already works with GET method?
My Angular request:
this.http.post<UserDto>("//localhost:8080/users", this.user, {withCredentials: true}).subscribe( user => {
alert("User created successfully.");
});;
Those are response headers i get:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Methods: POST,PUT,DELETE,GET,OPTIONS
Access-Control-Allow-Origin: http://localhost:4200
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 0
Date: Sun, 05 May 2019 09:22:55 GMT
Expires: 0
Pragma: no-cache
Vary: Origin
Vary: Access-Control-Request-Method
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
And my request headers:
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Connection: keep-alive
Host: localhost:8080
Origin: http://localhost:4200
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
My Spring Security configuration:
#Configuration
#EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.
cors().and().
csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and().addFilterBefore(
new StatelessCSRFFilter(), CsrfFilter.class);
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(ImmutableList.of("http://localhost:4200"));
configuration.setAllowedMethods(Arrays.asList("POST","PUT","DELETE","GET","OPTIONS"));
configuration.setAllowCredentials(true);
configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
I have found such an advice:
" I got it to work by adding a response filter for the pre-flight OPTIONS request that works without credentials.
<security-constraint>
<display-name>No check for options</display-name>
<web-resource-collection>
<web-resource-name>All Access</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>OPTIONS</http-method>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
I am not sure how to implement that solution is spring.
The CORS configuration has been set up correctly on the SpringFramework backend, as the methods succeed as expected, and Angular does set the cookies for GET requests. It is only POST operations that do not succeed if not preceded by HTTP.GET request.
Related
How to add custom metrics to /info endpoint in Spring Actuator 2.7.0?
Currently have the following related to actuator.
I have verified that info.app.version can retrieve the proper value from pom.xml using #Value.
pom.xml
<version>0.0.1-SNAPSHOT</version>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>2.7.0</version>
</dependency>
application.properties
info.app.version=#project.version#
management.endpoint.info.enabled=true
management.endpoints.web.exposure.include=info,health
But despite this I am only getting an empty response on /info.
Response header:
< HTTP/1.1 200
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/vnd.spring-boot.actuator.v3+json
< Transfer-Encoding: chunked
< Date: Wed, 15 Jun 2022 04:12:47 GMT
* Received 7 B chunk
* Received 5 B chunk
* Connection #26 to host localhost left intact
Response body :
{}
My understanding is any property under info is included in /info endpoint. Or does this not work on actuator v2+ ?
Source
From the Spring-Boot 2.6 release notes https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.6-Release-Notes#actuator-env-infocontributor-disabled-by-default
You need to enable the info env property:
management.info.env.enabled=true
Latest spring boot requires two things to be set up:
1- exposing the endpoint in application.properties file:
management.endpoints.web.exposure.include=info, health
You can use a wildcard and expose all endpoints if you want
management.endpoints.web.exposure.include=*
2- enabling info.env in application.properties:
management.info.env.enabled=true
I m using rest assured with latest version of java spring.
I try to simulate call to authenticate with post method and json body (contentType is application/json) but when my request is intercepted by my java spring application, the body is empty.. and my authenticate methods throw a 401.. this behavior is correct. But the empty body isn't.
I can see with ngrep and some functions with rest assured that all request are correctly done.
When i use curl,postman or ajax from js client i don't have this problem
#EnableAutoConfiguration
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserControllerImplTest {
#Test
public void testUserAuthenticateWitParams200() {
Map<String, Object> jsonAsMap = new HashMap<>();
jsonAsMap.put("email", "groschat.eu#gmail.com");
jsonAsMap.put("password", "groschat93**");
given().log().all()
.body(jsonAsMap)
.contentType("application/json; charset=UTF-8").
when()
.post(String.format("http://localhost:%s/api/users/authenticate", port))
.peek().
then()
.statusCode(is(200));
}
}
Here is the log from peek() function :
Request method: POST
Request URI: http://localhost:53850/api/users/authenticate
Proxy: <none>
Request params: <none>
Query params: <none>
Form params: <none>
Path params: <none>
Headers: Accept=*/* Content-Type=application/json; charset=UTF-8
Cookies: <none>
Multiparts: <none>
Body:
{
"password": "groschat93**",
"email": "groschat.eu#gmail.com"
}
Here is the request from dev tool inside chrome
Request headers:
POST /api/users/authenticate HTTP/1.1
Host: back-spring.dev
Connection: keep-alive
Content-Length: 62
Origin: https://front.dev
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
Content-type: application/json
Accept: */*
Referer: https://front.dev/
Accept-Encoding: gzip, deflate, br
Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7
Request Payload:
{"email":"martinbryan.eu#gmail.com","password":"groschat93**"}
Problem was Tomcat and a useless semicolon in the header Content-Type.
Tomcat wasn't able to read the content type with the semicolon with nothing following like charset. So when the request was read, server side, the default content type text/plain. RestAssured
So i changed tomcat by undertow and i don't use rest assured anymore but WebTestClient. See codes and pom.xml. Source of this problem wasn't expected.
#AutoConfigureWebTestClient
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
#ContextConfiguration(
classes={
server_spring.Application.class,
server_spring.config.WebSecurityConfig.class,
server_spring.config.GlobalConfiguration.class,
server_spring.config.MvcConfig.class,
server_spring.config.WebConfig.class
})
public class UserControllerImplTest {
#Autowired
private WebTestClient webClient;
#Test
public void testWithAnotherMethod() {
Map<String, String> jsonMap = new HashMap();
jsonMap.put("email","martinbryan.eu#gmail.com");
jsonMap.put("password","groschat93**");
webClient
.post()
.uri("/api/users/authenticate")
.header("Origin","https://front.dev")
.header("Referer","https://front.dev")
.header("Host", "back-spring.dev")
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromObject(jsonMap))
.exchange()
.expectStatus()
.isOk();
}
}
My pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
I have built Spring WS application (based on Spring WS 2.2.3) that exposes a small web service with couple of Operations. Each Operation receives input parameters to search a backend database and return response. Some of the parameters are mandatory (e.g. Street Name) and the Client have requested that if a request to the service is missing some of these mandatory parameters (e.g. empty Street Name) then my service should return proper SOAP Fault with HTTP status of 400.
My exception handling is working fine and I am able to return the correct SOAP Fault to the client if some a required parameter was missing form the request message and Spring WS takes care of the rest by wrapping a SOAP Fault and sends it back to the client with status code of 500 like the following:
HTTP/1.1 500 Internal Server Error
Server: Apache-Coyote/1.1
Accept: text/xml, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
SOAPAction: ""
Content-Type: text/xml;charset=utf-8
Content-Length: 503
Date: Thu, 10 Dec 2015 22:28:02 GMT
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:Client</faultcode>
<faultstring xml:lang="en">Street Name is required</faultstring>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Which is good except that I really want the HTTP status code to be '400 Bad Request' instead of the '500 Internal Server Error' I can't figure out how to change the status code from 500 to 400 and get similar response like the following:
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Accept: text/xml, text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
SOAPAction: ""
Content-Type: text/xml;charset=utf-8
Content-Length: 503
Date: Thu, 10 Dec 2015 22:28:02 GMT
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:Client</faultcode>
<faultstring xml:lang="en">Street Name is required</faultstring>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Any ideas?
I have a Spring MVC webapp, that as part of its operation runs off and performances several SQL queries, that can take up to 15 minutes to run.
If you delete the deployment while a query is running, the weblogic log will print the following stacktrace:
POST /MyWebapp/submitQuery HTTP/1.1
x-requested-with: XMLHttpRequest
Accept-Language: en-nz
Referer: http://server:1111/mywebapp/
Accept: */*
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)
Content-Length: 268
Connection: Keep-Alive
Cache-Control: no-cache
Cookie: JSESSIONID=KgJ5VnFLpWTp1ZNjwt3p1D4FHxmSQnPpTTwX18TDyMxnpgGBXWTD!1657710130; ADMINCONSOLESESSION=tSWjVnXJb6MPn0Bj9h4FPWvyzHC5pbCf2H20ZgfGHLTKpykMN82m!802748838
]] Root cause of ServletException.
java.lang.NoClassDefFoundError: org/apache/log4j/DefaultThrowableRenderer
at org.apache.log4j.spi.ThrowableInformation.getThrowableStrRep(ThrowableInformation.java:87)
at org.apache.log4j.spi.LoggingEvent.getThrowableStrRep(LoggingEvent.java:413)
at org.apache.log4j.WriterAppender.subAppend(WriterAppender.java:313)
at org.apache.log4j.WriterAppender.append(WriterAppender.java:162)
at org.apache.log4j.AppenderSkeleton.doAppend(AppenderSkeleton.java:251)
at org.apache.log4j.helpers.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:66)
at org.apache.log4j.Category.callAppenders(Category.java:206)
at org.apache.log4j.Category.forcedLog(Category.java:391)
at org.apache.log4j.Category.log(Category.java:856)
at org.apache.commons.logging.impl.Log4JLogger.debug(Log4JLogger.java:166)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:989)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227)
at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:300)
at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:183)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3717)
at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3681)
at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2277)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2183)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1454)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:207)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:176)
If you wait for queries to finish before deleting the deployment, then the errors will not be posted.
I've been told that it's not acceptable for this stacktrace to be thrown.
Two questions:
What actually happens if you delete a deployment while a thread is running?
How can I get Weblogic to handle it gracefully?
Can somebody please explain in plain English how this works (or at least why my structure doesn't)? I want a function called ExportLicenseInfo in my Jersey servlet resource, which I have called ExportResource, to map to http://example.com/myApp/export/software_licenses.{year}-{month}.{format}, for example: http://example.com/myApp/export/software_licenses_2013-10.csv
Servlet config in web.xml:
<servlet>
<servlet-name>ExportServlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.mycompany.app.ExportApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
My servlet mapping in web.xml:
<servlet-mapping>
<servlet-name>ExportServlet</servlet-name>
<url-pattern>/export</url-pattern>
</servlet-mapping>
My code with #Path annotations:
#Path("/export")
public class ExportResource {
...
#GET
#Produces({"text/csv", "application/json"})
#Path("/software_licenses_{year: [0-9][0-9][0-9][0-9]}-{month: [0-1][0-9]}.{format}")
public String ExportLicenseInfo( ... ) {
...
}
When I try to access the resource, I get a 404. Jersey trace log:
Feb 21, 2014 2:41:46 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 6 * LoggingFilter - Request received on thread http-bio-8080-exec-67
6 > GET http://localhost:8080/app/export/software_licenses_2013-10.csv
6 > host: localhost:8080
6 > connection: keep-alive
6 > cache-control: max-age=0
6 > accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
6 > user-agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36
6 > accept-encoding: gzip,deflate,sdch
6 > accept-language: en
6 > cookie: JSESSIONID=DB64E0B066BDEE8CABFC94686AD6ACDC.test; JSESSIONIDSSO=61B51CEED61F8F6CE8A8DB46B38BAC9F; i18next=en
Feb 21, 2014 2:41:46 PM org.glassfish.jersey.filter.LoggingFilter log
INFO: 6 * LoggingFilter - Response received on thread http-bio-8080-exec-67
6 < 404
Try mapping the jersey servlet like this:
<servlet-mapping>
<servlet-name>ExportServlet</servlet-name>
<url-pattern>/export/*</url-pattern>
</servlet-mapping>