Getting HTTP 404 error in Spring login - spring

Error:
HTTP Status 404 – Not Found
Type Status Report
Message /DemoTask/
Description The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
Apache Tomcat/7.0.90
Code:
import com.demo.bean.Login;
#Controller
public class LogController {
#RequestMapping({ "/login" })
public String showHome(#ModelAttribute("login") Login login) {
String name = login.getUname();
String password = login.getUpass();
if ((name.equals("hello")) && (password.equals("hello"))) {
return "redirect:admin.do";
}
return "login";
}
#RequestMapping({ "login" })
public String showLogin() {
return "login";
}
}

Ambigious Request Mapping for the uri "login".
Added request type to mapping as below
#Controller
public class LogController {
#RequestMapping(value = { "/login" }, method = RequestMethod.POST)
public String showHome(#ModelAttribute("login") Login login) {
String name = login.getUname();
String password = login.getUpass();
if ((name.equals("hello")) && (password.equals("hello"))) {
return "redirect:admin.do";
}
return "login";
}
#RequestMapping(value = { "login" }, method = RequestMethod.GET)
public String showLogin() {
return "login";
}
}

Related

Overloading SpringBoot #PostMapping controller method not working

I have faced some challenge and to describe shortly I created test application. Code you can see and error you can see below.
#RestController
public class TestController {
#PostMapping(value = "/test",params = { "a", "b" })
public String test(#RequestPart MultipartFile a, #RequestPart(required = false) MultipartFile b) {
return "test1";
}
#PostMapping(value = "/test", params = { "b" })
public String test(#RequestPart MultipartFile b) {
return "test2";
}
}
I`m trying to execute this request from postman:
And I`m getting such error in logs:
Resolved [org.springframework.web.bind.UnsatisfiedServletRequestParameterException:
Parameter conditions "a, b" OR "b" not met for actual request parameters: ]
The thing is, if I will put parameters also in postman (not in body, in request url: localhost:8080/test?b=anything) it will work fine, but I don`t need request params in url.
Is there some possible way to make it work?
I am able to override #PostMapping. But the type of the parameter should be different.
#PostMapping(value="/test" )
public String testApi(#ModelAttribute MultipartDTO multipartDTO) {
return "test1";
}
#PostMapping(value="/test" ,params = { "b" })
public String test(#RequestParam String b) {
return "test2";
}
/** DTO **/
#Data
public class MultipartDTO{
private MultipartFile a;
private MultipartFile b;
}
you can not map the same signature twice which contains the same Http methods then below error will occur.
java.lang.IllegalStateException: Ambiguous handler methods
try this one
#RestController
public class TestController {
#PostMapping("/test")
public String test(#RequestParam MultipartFile a, #RequestParam(required = false) MultipartFile b) {
return "test1";
}
#PostMapping("/test2")
public String test(#RequestParam MultipartFile b) {
return "test2";
}
}
You should try something like below.
#RestController
public class TestController {
#PostMapping(value = "/test")
public String test(#RequestParam MultipartFile a, #RequestParam(required = false) MultipartFile b) {
return "test1";
}
#PostMapping(value = "/test")
public String test(#RequestParam MultipartFile b) {
return "test2";
}
}

Default return error for white label erorr

I have this controller which is open when user is redirected.
#Controller()
public class RedirectController {
#RequestMapping(method = RequestMethod.GET, value = "/redirect")
#ResponseBody
public String handleRedirectMessage(HttpServletRequest request) throws Exception {
......
}
}
But when the match is not found I get Whitelabel Error Page. Is there some way to set default handler which is by default open when path is not correct?
You need add following property:
server.error.whitelabel.enabled=false
And implement org.springframework.boot.web.servlet.error.ErrorController interface and overrides its getErrorPath() to return a custom path to call when an error occurred:
#Controller
public class MyErrorController implements ErrorController {
#RequestMapping("/error")
public String handleError() {
//do something like logging
return "error";
}
#Override
public String getErrorPath() {
return "/error";
}
}
After that add error page for path "/error" Thymeleaf error.html.
Also you could add pager for different errors:
#RequestMapping("/error")
public String handleError(HttpServletRequest request) {
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if (status != null) {
Integer statusCode = Integer.valueOf(status.toString());
if(statusCode == HttpStatus.NOT_FOUND.value()) {
return "error-404";
}
else if(statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
return "error-500";
}
}
return "error";
}
You can find here full code example
and description.

Spring redirect from ErrorController

I have a number of generic error pages which are used by multiple applications other than the one I have control of. I would like to configure the Spring Boot error controller to do a redirect to one of these pages. Unfortunately it's not working.
Eg.
#Controller
public class MyCustomErrorController implements ErrorController {
#GetMapping(value = "/error")
public String handleError(HttpServletRequest request) {
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if (status != null) {
Integer statusCode = Integer.valueOf(status.toString());
if (statusCode == HttpStatus.NOT_FOUND.value()) {
return "redirect:https://www.example.com/error-404";
}
}
return "redirect:https://www.example.com/error-500";
}
#Override
public String getErrorPath() {
return "/error";
}
}
If for example I purposefully mistype a URL I can see the response has the Location header with the 404 URL I am expecting but the browser doesn't actually redirect. Any ideas if it's possible to do a redirect from within a custom ErrorController?
Could this be because I'm trying to test this from localhost, and Strict-Transport-Security is ignoring the response Location header value (which is on a FQDN)?
How about adding HttpServletResponse to the method param and use it for redirection?
HttpServletResponse response;
response.sendRedirect("https://www.example.com/error-404");
Reference HERE
Add the following properties in application.proerties file
server.error.whitelabel.enabled=false
try this.
#Controller
public class MyCustomErrorController implements ErrorController {
#GetMapping(value = "/error")
public String handleError(HttpServletRequest request) {
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if (status != null) {
Integer statusCode = Integer.valueOf(status.toString());
if (statusCode == HttpStatus.NOT_FOUND.value()) {
return "redirect:/error-404"; //remove your https://www.example.com
}
}
return "redirect:/error-500";
}
#Override
public String getErrorPath() {
return "/error";
}
}
** EDIT **
change the url mapping and try again:
error-404 -> error/404
error-500 -> error/500
#Controller
public class MyCustomErrorController implements ErrorController {
#GetMapping(value = "/error")
public String handleError(HttpServletRequest request) {
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if (status != null) {
Integer statusCode = Integer.valueOf(status.toString());
if (statusCode == HttpStatus.NOT_FOUND.value()) {
return "redirect:/error/404"; //remove your https://www.example.com
}
}
return "redirect:/error/500";
}
#Override
public String getErrorPath() {
return "/error";
}
}
error/404
#GetMapping("/error/404")
error/500
#GetMapping("/error/500")

Spring WEB MVC + produces = MediaType.IMAGE_JPEG_VALUE + #ResponseStatus(HttpStatus.FORBIDDEN) = HTTP status 406

I'm writing some code for user authorization. For users with 2 factored authorization enabled I'm writing code for 2fa secret update:
#RestController
public class CurrentUserController {
#PostMapping(value = "update-2fa-secret", produces = MediaType.IMAGE_JPEG_VALUE)
public byte[] update2FaSecret() {
UserEntity user = userRepository.findOne(currentUserId);
if (user.is2FaEnabled() != Boolean.TRUE)
throw new HttpForbiddenException("2fa disabled for current user");
String secret = createNewSecret();
user.setSecret2Fa(secret);
userRepository.save(user);
return createQRCode(secret, user.getEmail());
}
}
And Exception:
#ResponseStatus(HttpStatus.FORBIDDEN)
public class HttpForbiddenException extends RuntimeException {
............
}
And when Exception happens I get response from the server with 406 Http status and without body (content).
I don't understand why this happens and how to solve it. Can somebody explain it to me please?
I've solved this issue in the next way:
#RestController
public class CurrentUserController {
#PostMapping(value = "update-2fa-secret", produces = MediaType.IMAGE_JPEG_VALUE)
public byte[] update2FaSecret(HttpServletResponse response) {
UserEntity user = userRepository.findOne(currentUserId);
if (user.is2FaEnabled() != Boolean.TRUE) { //fix is here
response.setStatus(HttpStatus.FORBIDDEN.value()); //403
return new byte[0];
}
String secret = createNewSecret();
user.setSecret2Fa(secret);
userRepository.save(user);
return createQRCode(secret, user.getEmail());
}
}

Spring MVC 3, forwarding not working when using Ajax

I have very interesting problem. I am making log in page for my web app and I am sending login request via AJAX. If success I want to forward user to another page.
It seems that his is what happens. I send Ajax request, controller forwards me to need view (I see log in debug mode) but I stay on the same page, since I assume the page is waiting for AJAX response and for that reason forwarding does not happen.
I think this is also wrong way to approach this but since I am new to this don't know better. How can I log in and and forward user to next page.
Thank you.
Here is my code:
JS Code:
Page.authenticate = function() {
$.ajax({
url: "/login/authenticate/" + $('#username').val() + "/" + $('#password').val(),
type: "GET",
success: function(poi){
// alert("nesto");
}
});
return true;
}
Controller Class:
#Controller
public class LoginPageController {
private Logger logger = Logger.getLogger(this.getClass());
#Autowired
private UserManagement userManagement;
#RequestMapping(value="/login/authenticate/{username}/{password}", method=RequestMethod.GET)
public String authenticate(#PathVariable("username") String userName, #PathVariable("password") String password, Model model) {
if (userManagement.authenticateUser(userName, password)) {
String forward = "forward:/login/success";
return forward;
} else {
model.addAttribute("errorMessage", "Invalid Username/Password, please try again!");
return "/";
}
}
}
You need to response within #ResponseBody Annotation if you are using AJAX.
#RequestMapping(value="/login/authenticate/{username}/{password}", method=RequestMethod.GET)
public String authenticate(#PathVariable("username") String userName, #PathVariable("password") String password, Model model) {
if (userManagement.authenticateUser(userName, password)) {
String forward = "forward:/login/success";
return forward;
} else {
String forward = "forward:/login/error?message=Invalid Username/Password, please try again!";
return forward;
}
}
#RequestMapping(value="/login/success", method=RequestMethod.GET)
#Responsebody
public String handleMySuccessRedirect() {
return "Logged In successfully"
}
#RequestMapping(value="/login/error", method=RequestMethod.GET)
#Responsebody
public String handleMyExceptionOnRedirect(#RequestParamter("message") String message) {
return message;
}
Update:
#RequestMapping(value="/login/authenticate/{username}/{password}", method=RequestMethod.GET)
#ResponseBody
public String authenticate(#PathVariable("username") String userName, #PathVariable("password") String password, Model model) {
if (userManagement.authenticateUser(userName, password)) {
String response = "Logged Successfully";
return response;
} else {
String response = "Invalid Username/Password, please try again!";
return response;
}
}
There are a couple of things you can do here:
Don't return a view from your controller, instead return json, based on the response in json, set the location appropriately - window.location = 'home.action' - here is an example using ext-js
Let the login page perform a full fledged post, not an AJAX post.

Resources