Springboot: trying to map a logout url - There was an unexpected error (type=Method Not Allowed, status=405) - spring

I am trying to map a logout url in spring boot application. Every other mapping I have specified is working perfectly but this logout url mapping is refusing to map to the controller
this is the form with the submit command
<form method="post" action="/livechat/logout">
<input type="submit" value="Leave Chat"/>
</form>
this is the controller when you hit the submit button
#RequestMapping(value = "/logout", method = RequestMethod.POST)
public ModelAndView logout(HttpServletRequest request,
HttpServletResponse response) {
for (Cookie cookie : request.getCookies()) {
if ("name".equals(cookie.getName()) || "email".equals(cookie.getName())) {
// clear cookie
cookie.setMaxAge(0);
response.addCookie(cookie);
}
}
return new ModelAndView("redirect:/");
}
in my application.properties file I have this configuration for the server url definition
server.context-path= /livechat
#server port
server.port = 8081
When I click on logout i get this error
Fri Aug 05 11:56:22 WAT 2016
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'POST' not supported
when I look at the url borwser it seems correct but I get error responce
http://localhost:8081/livechat/logout
Please what be wrong. Kiindly assist!

Related

IllegalArgumentException: The HTTP header line does not conform to RFC 7230 when POST-accessing Spring Controller

I want to implement a user registration functionality with Spring. When I try to POST the data to the spring controller, the exception above is thrown. Surprisingly, GET Requests work on the controller.
#RestController
#RequestMapping(RestApi.ANONYMOUS + "register")
public class RegisterController {
#PostMapping(value="/new", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public UserRegistrationResultDto registerUser(#RequestBody UserRegisterDto dto) {
UserRegistrationResultDto result = registerService.registerUser(dto.getMail(),
dto.getPassword(), dto.getRepeatedPassword());
return result;
}
#GetMapping("/test")
public String test() {
return "get success";
}
}
The request that fails with error code 400 is the following:
POST http://localhost:8080/api/anonymous/register/new
Content-Type:application/x-www-form-urlencoded
{
mail=data&password=data&passwordRepeated=data
}
It throws the following exception:
java.lang.IllegalArgumentException: The HTTP header line [{: ] does not conform to RFC 7230 and has been ignored.
This get request however works:
GET http://localhost:8080/api/anonymous/register/test
I am using Tomcat 9 as a server.
Not sure how the POST request is submitted...but a space after : is required for HTTP header fields:
Content-Type: application/x-www-form-urlencoded

Getting 403 forbidden error using #PostMapping via rest api in spring boot project

I am getting 403 forbidden error on postman while accessing #PostMapping. However, #GetMapping is working fine with basic authentication
#PostMapping(value = { "/version" })
#ApiOperation(value = "Set Version")
#Monitor(useCase = "setApplicationVersion")
public void setApplicationVersion() {
System.out.println("Hey postman");
}
This is my #PostMapping method. Suggest something for the issue
Please post screenshot of what kind of request is being sent via postman and the type of content we are sending as same needs to be set at the controller level.
check if content type is set to application/json in the controller and when sending request from postman.

how to view spring csrf token in filter

i am using spring mvc 4.3 version. We are using spring csrf which is default. In one of the scenario i am getting invalid token error, but I see the token whatever I have got the same is been sent to server. Is there any way I can put log message to see server response to see the csrf token that is generated. on the UI JSP page i am using tag and in the page view source I could see the token. But i want to see in a filter from server side to make sure there is no other token missing on my page.
I have two tabs on my page. Whenever I change tabs I am getting into this token invalid issue. Could you help me how to access this token details in my custom filter.
I tried the AOP like this any changes required?
#Aspect
public class AfterGenerateCsrfTockenAspect {
protected transient ITSLogger logger = LogManager.getLogger(this.getClass().getName());
#AfterReturning(
pointcut = "org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.generateToken(..)",
returning = "result"
)
public void logGeneratedCsrfToken(Object result) {
logger.debug("CSRF token was generated. :::: " + result);
}
}
Is there any way I can put log message to see server response to see the csrf token that is generated
Yes, AOP to the rescue. For example you can log token each time it was generated:
#Aspect
#Slf4j // lombok for logging
public class AfterGenerateCsrfTockenAspect {
#AfterReturning( // use here FQDN of your Token generator method
pointcut = "org.springframework.security.web.csrf.CookieCsrfTokenRepository.generateToken(..)",
returning = "result"
)
public void logGeneratedCsrfToken(Object result) {
log.info("CSRF token '{}' was generated.", result);
}
}
By default spring stores csrf token in session. we can access csrf token from session attributes
String key ="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN"
HttpSession session = request.getSession(true);
CsrfToken token =(CsrfToken) session.getAttribute(key);

Spring 3.2 REST API add cookie to the response outside controller

I'm using Spring 3.2.4 and Spring Security 3.2.3 to handle RESTful API call to "get security token" request that returns the token (which would be used to secure subsequent requests to the service). This is a POST request which has a body with username and password and is processed in the controller:
#RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public SessionTokenResponse getSessionToken(#RequestBody Credentials credentials, ModelAndView interceptorModel) throws AccessException {
final String token = webGate.getSessionTokenForUser(credentials.getUsername(), credentials.getPassword());
LOGGER.debug("Logged in user : " + credentials.getUsername());
interceptorModel.addObject(SessionConstants.INTERCEPTOR_MODEL_TOKEN_KEY, token); // Used by post-processing in interceptors, e.g. add Cookie
return new SessionTokenResponse(ResponseMessages.SUCCESS, token);
}
After the controller has successfully finished processing the request I would like to add a cookie with the token to the response.
I tried HandlerInterceptorAdapter implementation, but I cannot find the way to the the 'token' from the response or ModelAndView:
#Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView interceptorModel) throws Exception {
final String token = (String) interceptorModel.getModel().get(SessionConstants.INTERCEPTOR_MODEL_TOKEN_KEY);
if (token != null) {
final Cookie obsso = new Cookie(cookieName, token);
obsso.setPath(cookiePathUri);
obsso.setDomain(cookieDomain);
obsso.setMaxAge(cookieMaxAge);
response.addCookie(obsso);
}
}
The interceptorModel is null .
It seems that Spring MVC doesn't provide it to the postHandle since the #ResponseBody has been already resolved and there is no need for the ModelAndView anymore (this is just my assumption based on the debugging).
What is the correct way of achieving that (add cookie to the response) outside the controller in the interceptor or maybe listener?
To retrieve the token you can use the request object
request.setAttribute(SessionConstants.INTERCEPTOR_MODEL_TOKEN_KEY, token);
and then in the postHandle
String token = ( String ) request.getAttribute(SessionConstants.INTERCEPTOR_MODEL_TOKEN_KEY);
However I don't think you can add a cookie to the response object in postHandle as the response is already committed.
Perhaps you could store the token information on the servlet context instead.
In your controller, add the token information to the servlet context.
Then implement preHandle, so that every api call can check if token for that user exists on servlet context, if so you can add cookie to the response.

Flash attributes in Spring MVC 3.1 not visible to redirected JSP

I am using Spring 3.1's new Flash Attribute support to set flash attributes on a RedirectAttributes object in a Controller and then invoking a redirect. That redirect request is in turn caught by a filter which then sends it on its merry way to the JSP that it's intended for. The problem: I can't see the flash attributes either from within the filter's doFilter() method or from the JSP. Non-flash (URL) attributes make it just fine.
Controller that does the redirect:
#RequestMapping("/pages/login")
public String login (HttpServletRequest request, Map<String, Object> model, RedirectAttributes redirectAttributes) {
model.put("userId", "batman");
String redirectUrl = request.getParameter("redirectUrl");
if (redirectUrl != null) {
redirectAttributes.addAttribute("attr1","ababab");
redirectAttributes.addFlashAttribute("flashAttr1", "flashflash");
for (Iterator<String> iterator = model.keySet().iterator(); iterator.hasNext();) {
String key = iterator.next();
redirectAttributes.addFlashAttribute(key, model.get(key));
}
return "redirect:"+redirectUrl;
} else {
return "pages/login";
}
}
The filter which picks up the redirect doesn't do anything interesting in this case:
public void doFilter (ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
//if (httpRequest.getSession().getAttribute("userId") == null) {
//...do some stuff here which invokes controller above as well as the redirect
//} else {
chain.doFilter(request, response);
//}
}
The page that gets redirected to following the filter:
...
<title>Test Web App 1</title>
</head>
<body>
<p>Flash attribute: <c:out value="${flashAttr1}"/></p>
<p>Welcome <c:out value="${userId}"/>!</p>
</body>
</html>
Neither flashAttr1 nor userId end up being populated in the page. The attr1 non-flash attribute the controller set does appear in the URL params of the page, so that seems to work.
Here is some output from log4j after I set springfamework.web to DEBUG:
19:15:44,406 DEBUG http-8080-1 view.ContentNegotiatingViewResolver:494 - Returni
ng redirect view [org.springframework.web.servlet.view.RedirectView: name 'redir
ect:http://my_hostname:8080/test-webapp-1/protected/protected_page.jsp';
URL [http://my_hostname:8080/test-webapp-1/protected/protected_page.jsp]]
19:15:44,406 DEBUG http-8080-1 servlet.DispatcherServlet:1155 -
Rendering view [org.springframework.web.servlet.view.RedirectView: name
'redirect:http://my_hostname:8080/test-webapp-1/protected/protected_page.jsp';
URL [http://my_hostname:8080/test-webapp-1/protected/protected_page.jsp]] in
DispatcherServlet with name 'dispatcher'
19:15:44,421 DEBUG http-8080-1 support.DefaultFlashMapManager:199 - Saving Flash
Map=[Attributes={userId=batman, flashAttr1=flashflash}, targetRequestPath=/test-
webapp-1/protected/protected_page.jsp, targetRequestParams={attr1=[ababab]}]
19:15:44,421 DEBUG http-8080-1 servlet.DispatcherServlet:913 - Successfully comp
leted request
Following a brief stop at the filter I've shown above, I am taken to the page with URL
http://my_hostname:8080/test-webapp-1/protected/protected_page.jsp?attr1=ababab
But neither of the attributes I expect that JSP to find are displayed. I have also debugged through the doFilter() method shown above and failed to find the flash attributes in the request's session.
I'm not sure exactly what's wrong at this point. Everything works as expected except for those flash attributes. If there is anything else I should provide to make the situation more clear, I will be happy to.
Ran into this issue a few months ago with AJAX-related redirects. If you use a read-only HTTP POST pattern, you can specify a #ResponseStatus to simulate a POST. Also be sure to have your method return a View or ModelAndView (as opposed to String) so that Spring knows to look up the Flash scope for the given #RequestMapping.
Pseudocode:
#RequestMapping(...)
#ResponseStatus(OK)
public ModelAndView login (...) {
...
}

Resources