I can't send a POST request using my browser? - spring-boot

I am working on an application using Spring Boot MVC and I have a login page and whenever I input data on the forms using chrome my browser doesn't redirect me to the page I've specified in my Controler class but instead It sends a GET request where it should be sending a POST request. This is my controller class
#Controller
#RequestMapping("/login")
public class loginController {
private final AuthService authService;
public loginController(AuthService authService) {
this.authService = authService;
}
#GetMapping
public String returnLogIn() {
return "login";
}
#PostMapping
public String login(#RequestParam String username, #RequestParam String password, Model model) {
User user = null;
try {
user = this.authService.login(username, password);
model.addAttribute("User", user);
return "redirect:/home";
} catch (InvalidArgumentsException exception) {
model.addAttribute("hasError", true);
model.addAttribute("error", exception.getMessage());
return "login";
}
}
}
As you see if the login is successful then I should be redirected to the home page but It doesn't happen I get redirected to the login page again and all that changes is the URL in it the parameters I've given are appended. But when I use POSTMAN everything works just fine a POST request is sent and I get redirected to the /home page just like I've specified it in my Controller class. But I don't know why this wont happen when I use chrome. Having to use POSTMAN everytime I do a small change is really time-consuming. Also this is the HTML form
<form id="form-id" th:action="#{/login}" th:method="post">
<div class="mb-3">
<input type="text" class="form-control" name="username" id="username" aria-describedby="emailHelp"
placeholder="User Name">
</div>
<div class="mb-3">
<input type="password" class="form-control" name="password" id="password" placeholder="Password">
</div>
<!-- TODO use hasError set it in the model -->
<div th:if="${hasError}">
<span class="error text-danger" th:text="${error}"></span>
</div>
<div class="text-center"><button type="submit" class="btn btn-color px-5 mb-5 w-100 btn btn-dark" >Login</button></div>
</form>
I don't think there is something wrong with my code since everything works fine when I use POSTMAN but I really don't know why It wont work when I use my browser. Javascript is enabled in my browser I really don't know what seems to be the issue. I also tried mapping the POST request to a different URL but still I get the same issue.

I also believe that your code sample has no problem because if there is a problem it should not respond correctly from POSTMAN,Unless you have configured the application server and restricted requests from the browsers.
The suggestion I can give you is to monitor requests when sending a request using tools like Fiddler (Fiddler is a powerful web debugging proxy),etc.. ,to see if both requests send the same parameters to server .

Related

Missing request attribute 'projektId' of type String | Thymleaf Form with just a String

I'm working on a Projekt where you can add workers to projects with their ids.I am using springboot, thymeleaf and a database means you give a project and a worker Id and the programm adds the worker to the project.workerlist. The Problem ist that I get this error:
Required request parameter 'projektId' for method parameter type String is not present
My HTML Form looks like this
<form action="#" th:action="#{neuenMitarbeiterzuProjektHinzufuegen}" method="post">
Projekt ID: <input type="text" th:value="*{projektId}" required/><br>
Mitarbeiter ID: <input type="text" th:value="*{mitarbeiterId}" required/><br>
<br>
<input type="submit" value="Mitarbeiter hinzufügen"/>
<input type="reset" value="Clear"/>
</form>
My Post Route Handler Method looks like this
#PostMapping(value="/neuenMitarbeiterzuProjektHinzufuegen")
public String neuenMitarbeiterzuProjektHinzufuegen(#RequestAttribute(value = "projektId") String projektID, #RequestAttribute(value = "mitarbeiterId") String mitarbeiterID,Model m)
{
Optional<Projekt> projekt = projektRepository.findById(Long.parseLong(projektID));
projektRepository.findById(Long.parseLong(projektID)).get().mitarbeiterHinzufuegen(mitarbeiterRepository.findById(Long.parseLong(mitarbeiterID)).get());
return "redirect:Projekte";
}
Looking at your code example I think you should be using #RequestParam not #RequestAttribute. Param is for things posted from the user (web) side and attribute you can set on the server side.
This blog has some explanation on the difference of #RequestAttribute https://www.logicbig.com/tutorials/spring-framework/spring-web-mvc/request-attribute.html

Spring: redirect from POST method doesn't work

I'm trying to get my Spring controller recieve POST request. I want to get the body of post request and show it on web page. I send requests via Postman. My controller receives it, but somehow, when I try to redirect to another page as usual, Spring renders the html template and sends it back to Postman.
My code:
#GetMapping("/webhooks")
public String webhooks(Model model) {
model.addAttribute("response", "webhooks");
return "connected";
#PostMapping("/webhooks")
public String webhooks(String payload, Model model) {
model.addAttribute("response", payload);
return "connected";
}
My connected.html template:
<body>
<a href="/" >Home</a>
<h3>Connected!</h3>
<div>
<button onclick="refreshToken()">Refresh Token</button>
<br /><br />
<button onclick="newCustomer()">Create new customer</button>
<button onclick="invoice()">Create new invoice</button>
<br />
<div><code id="result" th:text="${response}"></code></div>
</div>
</body>
This is what I see in Postman window:
But I expect to see the same form (as on the picture) in my browser and not in Postman. I want to redirect to this page and not to send this page back to Postman. I have a few similar methods in other controllers which are completely identical, but they work correctly.
What am I doing wrong? Thank you in advance.
I have the same issue as you have, I tried different ways to fix this problem but none of them worked for me. But you could give it a try:
#GetMapping("/webhooks")
public RedirectView webhooks(Model model) {
//Do what you want
return new RedirectView("/connected");
#PostMapping("/webhooks")
public RedirectView webhooks(String payload, Model model) {
//Do what you want
return new RedirectView("/connected");
}
This didn't work out for me but it might help you out. You use the RedirectView class from Spring and enter the URL to the endpoint.
Please let me know if it worked for you!

How to handle session to keep login information using Spring MVC

I want to make login form with Spring MVC using Hibernate.
I found that I need to use 'session' to keep login information.
So, I use it in 'Controller.java', '.jsp'.
But It seems didn't work.
Below is my code. Controller.java:
#Controller
public class PassengerController {
#Autowired
private PassengerService passengerService;
public void setPassengerService(PassengerService passengerService) {
this.passengerService = passengerService;
}
#RequestMapping(value = "/login")
public String login(HttpSession session, HttpServletRequest request) {
String id = request.getParameter("idInput");
String pw = request.getParameter("pwInput");
// check DB
// if it is right, add session.
session.setAttribute("id", id);
session.setAttribute("pw", pw);
return "flightschedule";
}
#RequestMapping(value = "/logout")
public String logout(HttpSession session) {
session.invalidate();
return "flightschedule";
}
}
Below is part of flightschedule.jsp:
<c:if test="${sessionScope.loginId eq null}">
<!-- Not login: show login button -->
<div class="loginArea">
<form action="${loginAction}"> <!-- // URL '/login' -->
<input type="text" name="idInput" placeholder="ID" class="loginInput">
<input type="password" name="pwInput" placeholder="PASSWORD" class="loginInput">
<input id="loginButton" type="submit" value="login">
</form>
</div>
</c:if>
<c:if test="${sessionScope.loginId ne null}">
<!-- already login: show logout button -->
<div class="loginArea">
<form action="${logoutAction}"> <!-- // URL '/logout' -->
<input type="button" name="idInput" id="loginInfo" value="Welcome ${sessionScope.loginId}">
<input id="logoutButton" type="submit" value="LOGOUT">
</form>
</div>
</c:if>
I intended that when session.id exists, show log out button and when session.id doesn't exist, show login button.
I don't want to use interceptors or spring security etc..
I thought they're too complex to my little project.
And, I have login/logout form at all most of my pages. I don't use a separate page to login.
So I don't want to use interceptor. I just want to check whether session key exists in some jsp pages. Depending on its presence, I want to change page's view.
Above's code work partly. When login, it shows 'Welcome userId'.
But, when I click page's logo(then go to the first page), It still show 'login' button. It have to show 'log-out' button becuase session.loginId exists!
Do you have any solution?
In login method you put
// check DB
// if it is right, add session.
session.setAttribute("id", id);
session.setAttribute("pw", pw);
but on JSP check sessionScope.loginId , looks like you should check attribute with name id.

How to post Antiforgery token from IdentityServer 3

I am using IdentityServer 3 for authentication. When user is authenticated then IdentityServer makes a 'POST' request to client's application url. For example http://localhost/home so far so good everything is working fine.
My Client application is developed in ASP.NET Core. In client application i want to validate every POST request. So instead of adding ValidateAntiForgeryToken attribute on each action method, i have created a middleware that validates every POST request.
public class ValidateAntiForgeryTokenMiddleware
{
private readonly RequestDelegate _next;
private readonly IAntiforgery _antiforgery;
public ValidateAntiForgeryTokenMiddleware(RequestDelegate next, IAntiforgery antiforgery)
{
_next = next;
_antiforgery = antiforgery;
}
public async Task Invoke(HttpContext httpContext)
{
if (httpContext.Request.Method.ToUpper() == "POST")
{
await _antiforgery.ValidateRequestAsync(httpContext);
}
await _next(httpContext);
}
}
The problem here is since identityserver is also making POST, the middleware tries to validate that request but the POST request fails with the following error
"The required antiforgery cookie
\".AspNetCore.Antiforgery.AXelvXewLHI\" is not present."
In Identity Server i have custom login page. and i have configured anti-forgery-token in login page.
<div ng-show="model.loginUrl">
<div class="cr-login-dialog col-md-6 col-md-offset-3">
<form name="form" method="post" action="{{model.loginUrl}}" class="form-horizontal" role="form">
<anti-forgery-token token="model.antiForgery"></anti-forgery-token>
<div class="form-group">
//user name controls goes here
</div>
<div class="form-group">
//password controls goes here
</div>
<div class="form-group" ng-show="model.allowRememberMe">
// remember me controls goes here
</div>
</form>
</div>
</div>
You should separate out your anti-xsrf middleware to only run on your requests, not the requests to IdentityServer. IdentityServer does its own anti-xsrf token unrelated to MVC's implementation (as IdentityServer has no dependencies on MVC).

Spring relationships between tables in view

Well, I started a new project using Spring MVC (I'm beginner in technology) and soon I had a basic question which I am unable to find on the internet, maybe the reason that I'm doing wrong or implementing the wrong question.
I have a form in which the data will be persisted are in two different tables.
What better way to do this?
I created two related tables, one called "Agency" and another called "Login". An "Agency" may contain one or more "Login" (# OneToMany), but the problem takes the view creation time, because data from both tables will compose a single form. With some research I noticed that I can not have two modelAttribute in my form.
I apologize for the mistakes in English.
Best regards!
if the mapping is correct and Agency contain one or many login, what you have to do is render the Agency in the model and view and in your form iterate the logins
<form:form id="foo"
method="post"
action="url"
modelAttribute="agency">
<form:input type="hidden" path="id"/>
<c:forEach var="login" items="${agency.logins}"
varStatus="login_index">
<form:input type="hidden" path="login.id" />
</c:foreach>
</form:form>
thanks for the reply.
But is not it :(
I have a form in which the data will be persisted are in two different tables.
<form class="form-signin" method="post" action="addAgency">
<div class="input-group">
<span class="input-group-addon entypo-user"></span>
//Table Agency
<spring:bind path="tenant.firstName"/>
<input class="form-control" placeholder="Nome"/>
//Table Login
<spring:bind path="login.email"/>
<input class="form-control" placeholder="Nome"/>
</div>
//Rest of my form...
</form>
In my view I have the annotation "bind" Spring, searching in the internet I found this way to make the connection between the controller and the view for persist two tables.
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(#ModelAttribute("tenant") Agency tenant, #ModelAttribute("login") Login login, ModelMap map) {
Agency agency = dashboardFacade.getAgency();
map.addAttribute("agency", agency);
if (tenantResolver.isMasterTenant()) {
//Here is the problem!!
// Add an attribute in my view of type login and agency, but i don't kwon if it is correct.
map.addAttribute("tenant", tenant);
map.addAttribute("login", login);
return "landing/index";
} else {
return "dashboard/home";
}
}
The method below to save an agency and login.
// Add a new agency
#RequestMapping(value = "/addAgency", method = RequestMethod.POST)
public String addAgency(#ModelAttribute("tenant") Agency agency, #ModelAttribute("login") Login login, Model model, final RedirectAttributes redirectAttributes) {
agency = dashboardFacade.addAgency(agency);
login = dashboardFacade.addLogin(login);
return "redirect:" + getAgencyFullUrl(agency);
}
What better way to do this?
Thank you

Resources