How to create a session object? - java

I am creating a login page for my web application. I want to create a session object whenever
a new user logged in. I know the concept of sessions, but i didnt used that before. Can i do it with a simple class. Or, i have to move to servlet.
If i shall do it with a simple class means, how to create a session object.
This is my scenario...
The HTML CODE:
<table>
<tr>
<td>User Name: </td><td><input id="uName" class="required" type="text"
size="5" /></td>
</tr>
<tr>
<td>Password: </td><td><input id="pwd" class="required" type="text" size="5"
onclick="login()"/></td>
</tr>
</table>
The JS Code:
function login(){
var userDetails = { uName : null, pwd : null };
dwr.util.getValues(userDetails);//Yes, i am using DWR.
LoginAuthentication.doLogin(userDetails, loginResult);
}
function loginResult(nextPage){
window.location.href = nextPage;
}
The Java Code:
public class LoginAuthentication
{
public String doLogin(User user) throws SQLException, ClassNotFoundException{
String userName = user.getUserName();
boolean loginResult = verifyUser(user);//Another method that verifies user details with the DB.
if (loginResult == true){
/* Here I have to create session object,
and i want to add the current username in that object. How to do it.*/
return "MainPage.html";
}
else{
return "loginRetryPage.html";
}
}
The concept that was given to me about session is pretty simple and clear. I have to create a session object after a valid user input & add the user name to that object, Destroy the object when logout was clicked. But i didnt worked on sessions before. I mean, i dont know the syntax to create a session variable.
How shall i create a session Object here?
Any suggestions would be more appreciative!!!
Thanks in Advance!!!

In a servlet a session is obtained with the following line:
Session session = request.getSession();
And to get the request object with DWR, you do (see here):
WebContext ctx = WebContextFactory.get();
HttpServletRequest request = ctx.getHttpServletRequest();
(The HttpServletRequest contains all data about the HTTP request that has been sent by the browser to the server)

It is better to always use request.getSession(false); after successful login.

Related

Why does my browser send a GET request on a form where it should be sending a POST request[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, HttpServletRequest request) {
User user = null;
try {
user = this.authService.login(username, password);
model.addAttribute("User", user);
request.getSession().setAttribute("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:method="POST" th:action="#{/login}">
<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 really don't know what seems to be the issue
As mentioned I can't send POST request using chrome but everything works fine with POSTMAN.
GET request instead of POST - As you can see a GET request is being instead where it Should be a POST request and here with Postman everything works fine I get redirected to the main page :
Postman request
I really don't know what to do as mentioned I cannot continue to work on the project because I need the user's session
I also uploaded the project on gitlab you can find it here:
https://gitlab.com/nisizenuni/betstar
When using POST in spring forms, the values that you pass from the form are not passed as query parameters. This happens when you use GET method action in some form.
So this is the reason that postman works but your frontend does not work in combination with backend. In postman you send the request correctly as you manually define the request parameters and so the controller can serve the request correctly. Your frontend however does not send the values as query parameters and so your controller does not correctly serve the request.
You can correct this by making the following changes.
First create a simple DTO object, where Spring could bind the passed values , which arrive in the body of the JSON request.
public class UserInfo {
private String userame;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
Then you can define your controller as
#PostMapping
public String login(#ModelAttribute UserInfo userInfo, Model model, HttpServletRequest request) {
String username = userInfo.getUsername();
String password = userInfo.getPassword();
.... same as the existing controller that you have
}
Also in Frontend you need to define your form as
<form id="form-id" th:method="POST" th:action="#{/login}" th:object="${userInfo}">

How to generate a session id each time a user login into the website?

<form action="<%=request.getContextPath()%>/login" method="post">
Email: <input type="email" name="email">
Password : <input type="password" name="psw">
<button type="submit" value="submit">Submit</button>
</form>
I have this login form.After submitting the values, it goes to the controller where the user authentication takes place and after authentication it moves to the home page.I want to generate a session id every time a user login so that, that user id can be used to get other information of the user(i.e some details like mobile no,address etc according to the need) that were filled during the registration.
I am doing all this using jsp and mvc.
Thanks in advance.
public static String getToken() {
return String.valueOf(System.currentTimeMillis()).substring(8, 13) + UUID.randomUUID().toString().substring(1,10);
}
or
public static String getUUID() {
return UUID.randomUUID().toString();
}

How to obtain csrf token in a velocity macro when using spring security

I am trying to create a custom login screen for a spring web security enabled application, and I cannot figure out how to pass the csrf token to velocity (no, I cannot use JSP at the moment).
The model looks something like this:
#RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView login(
#RequestParam(value = "error", required = false) String error,
#RequestParam(value = "logout", required = false) String logout
ModelAndView model = new ModelAndView();
if (error != null) {
model.addObject("error", "Invalid username or password!");
}
if (logout != null) {
model.addObject("msg", "You've been logged out successfully.");
}
model.setViewName("login");
return model;
}
And the relevant section of the velocity template looks like (taken and modified from a jsp example):
<form name='loginForm' action="/login" method='POST'>
<table>
<tr>
<td>User:</td>
<td><input type='text' name='username' value=''></td>
</tr>
<tr>
<td>Password:</td>
<td><input type='password' name='password' /></td>
</tr>
<tr>
<td colspan='2'><input name="submit" type="submit" value="submit" /></td>
</tr>
</table>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
Of course, the ${_csrf.parameterName} and ${_csrf.token} variables are empty, so this only works if I disable csrf protection. So my main question is: how do I fill them in the model (or anywhere else)?
I have found the solution, the main point is that the csrf token is injected into the HttpServletRequest by the CsrfFilter, and you can get the HttpServletRequest object by just adding a HttpServletRequest parameter to your method that handles the request mapping.
So the changes that needed to be done are:
#RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView login(
#RequestParam(value = "error", required = false) String error,
#RequestParam(value = "logout", required = false) String logout,
HttpServletRequest request
){
...
CsrfToken csrfToken = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
if (csrfToken != null) {
model.addObject("_csrf",csrfToken);
}
...
Just to share my little bit, I initially started by using #P.Péter's solution which was fine. but as my application grew to have so many forms, i decided it was too cumbersome using that snippet for every form that I needed to protect from csrf intrusions, so here's what I did so I don't have to repeat across my application.
#ControllerAdvice
public class CsrfControllerAdvice {
#Autowired
private HttpServletRequest request;
#ModelAttribute("_csrf")
public CsrfToken appendCSRFToken(){
//HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
return (CsrfToken) request.getAttribute(CsrfToken.class.getName());
}
}
POINT - The idea is to use a #ControllerAdvice which gets called on entering any Spring Controller to attach the CsrfToken to the resulting View using the #ModelAttribute("<attribute-name>") annotation.
NOTE 1 - This _csrf model attribute gets attached for all Views, hence if you want to limit the _csrf processing to selected URLs or Views, see this resource here for very nice samples on how to do that.
NOTE 2 - Notice how I commented out the following line?
//HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
That's because in my case the Autowired HttpServletRequest instance is sufficient for my scenario. However some situations may warrant that you use the commented out instance e.g when you need to obtain the request object from some part of your application that isn't necessarily request scoped... See #Samit G's answer as pointed out in this thread here for more information.

How can I send my requestdispatcher to two different jsp pages path?

I have made a registration form with the use of JSP, beans and JDBC (MVC)
In my servlet, I have the following code..
if ("editRegister".equalsIgnoreCase(action)) {
StudentBean user = new StudentBean();
user.setName(Name);
user.setStudID(ID);
user.setCourse(Course);
user.setEmail(Email);
db.addRecord(Name, ID, Name, Email);
set the result into the attribute
request.setAttribute("StudentBean", user);
RequestDispatcher rd;
rd = getServletContext().getRequestDispatcher("/DisplayRegistry.jsp");
rd = getServletContext().getRequestDispatcher("/UpdateRegistry.jsp");
rd.forward(request, response);
Basically, i want to send my requestDispatcher to two jsp pages so that I can display another form with predefined values inside the form.
e.g.
<jsp:useBean id="StudentBean" scope="request" class="ict.bean.StudentBean"/>
<% String email = StudentBean.getEmail() != null ? StudentBean.getEmail() : ""; %>
<form method="get" action="updateregistry">
<input type="text" name="email" maxlength="10" size="15" value="<%=email%>">
</form>
However, the problem is it displays null instead of the value as the requestDispatcher is only sent to one path.
Your practice of having two forwards makes no sense
rd = getServletContext().getRequestDispatcher("/DisplayRegistry.jsp");
rd = getServletContext().getRequestDispatcher("/UpdateRegistry.jsp")
Instead you can set the value to the session , so that you can access it in both the pages (throughout the application session).
so ,
HttpSession session=request.getSession(false);
session.setAttribute("StudentBean", user);
You can get the values from the session and have a single request dispatcher
Hope this helps !!

How do I show error information in web form?

This question is related to this. But since I haven't solved that question yet, I want to restate my problem a bit. I'm using Java Jersey REST API as my backend web service. The client side is a simple web form HTML page. Basically what I want is: If the user submits a web form and there are some errors caused by database unique constraint violation, I want the user to see an error message showing along with the id field in the form such as "ID already exists!". The web form is a simple form.html:
<form action="/myapp/rest/customer/created" method="POST">
<table border="1">
<tr>
<td>Customer name:</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>Customer ID:</td>
<td><input type="text" name="id"></td>
</tr>
<tr>
<td>Customer DOB:</td>
<td><input type="text" name="dob"></td>
</tr>
</table>
<br/>
<input type="submit" value="Submit">
</form>
If there is an error occurred, how to pass the error information from Jersey API to the client-side? My server-side POST call associated with this form submission is as follows:
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Path("created")
public Response createCustomer(#FormParam("id") int id,
#FormParam("name") String name, #FormParam("dob") Date dob)
throws ServletException, IOException {
URI uri = URI.create(uriInfo.getPath());
Response r;
r = Response.created(uri).build();
try {
dbController.create(id, name, dob); //This may throw exception.
} catch (DataAccessException ex) {
//To do: How to pass the error message to the client-side UI via e.g., Ajax?
}
return r;
}
First of all add this somewhere in your code. It will display the error message:
<span id="errorDiv" name="errorDiv" class="errorDiv" ></span>
Next, modify your form declaration as:
<form action="/myapp/rest/customer/created" method="POST" onsubmit="return checkForm()">
Before submitting the form it will call checkForm() function. if the function returns true then it will post the form. if not then it will prevent form from submission and display error message.
Assuming that you are submitting the form contents by using jQuery/AJAX calls. You can return a String(default value = 'success') from the server. In case there is an error change the specific string and return it and check the value client-side.
responseTxt is the value returned.
function checkForm(){
//get values from form
var name= $("#name").val();
var id= $("#id").val();
var dob= $("#dob").val();
$.post('DESTINATION',{name:name,id:id,dob:dob},function(responseTxt) {
//MAKE YOUR CHECK HERE. JUST AN EXAMPLE
if (responseTxt.substring(0,4)=='succ'){
//redirect to destination
return true;
}else{
//display error in errorDiv span
$('#errorDiv').html('<font color=red>Wrong username or password.</font>');
//prevents form to be submitted
return false;
}
});
}
Hope it helps

Categories