I am working on a web application of my own.Iam using Spring-mvc3 architecture n my application.I want to add authentication to my application.I thought of doing it by sessions but am not able to do so.I have created a login page and after login am able to authenticate and go to next page and get data that i have saved during session creation.Then after that when am navigating to another page my session data that i have saved is getting lost and when iam trying to get the session id am getting a new session id which is different from the one the got created at the time of authentication please check this and provide me the appropriate answer.
#RequestMapping(value = "checkLogin.action")
public String validateLogin(
#ModelAttribute("loginDto") LoginDto loginDetails,
HttpServletRequest request) {
boolean validUser;
try {
validUser = userDao.validateLogin(loginDetails);
if (validUser) {
HttpSession session = request.getSession();
if (session.isNew()) {
logger.debug("New Session is Created");
System.out.println("Session id is" + session.getId());
} else {
logger.debug("Not a New Session");
System.out.println("Session Id" + session.getId());
}
//session.setMaxInactiveInterval(1000);
session.setAttribute("LoginData", loginDetails);
session.setAttribute("loggedUser",true);
return "home";
}
return "redirect:loginPage.action?message=Unable to Login invalid Id/Password";
} catch (DaoException e) {
logger.error("Problem in UserDao");
return "redirect:loginPage.action?message=Unable to Login invalid Id/Password";
} catch (Exception e) {
logger.error("problem validating User Login");
e.printStackTrace();
return "redirect:loginPage.action?message=Unable to Login invalid Id/Password";
}
}
this is how am setting data in my session and am able to retrieve that set attributes in view home to which on success it goes to, from home if i go to another view there am not able to get that data.
I wanted to know using anchor tag for navigating to another page clears the session data??????
Related
I've created a simple login web where the user enters the email and password and checks if the user and password are correct then he gets redirected to a welcome.jsp page , where it says login success , I'm checking 3 emails and passwords and creating session for each one , the problem I'm facing is that if the user enters the email or password wrong after 3 attempts he will be blocked for a certain amount of time and after the time expires he can try again , I can't think of a way of doing this , is there a way in which this could be done ?
import java.io.*;
import jakarta.servlet.http.*;
import jakarta.servlet.annotation.*;
//#WebServlet(name = "loginController", value = "/login")
#WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws
IOException {
String email = request.getParameter("email");
String password = request.getParameter("password");
String er = "Invalid user info";
int attempts = 3;
PrintWriter printWriter = response.getWriter();
LoginBean loginBean = new LoginBean();
loginBean.setEmail(email);
loginBean.setPassword(password);
try
{
if(email.equals("Mhamdoon4#gmail.com") && password.equals("pass001"))
{
System.out.println("Admin's Home");
HttpSession session = request.getSession(); //Creating a session
session.setAttribute("Mohammed", email); //setting session attribute
request.setAttribute("email", email);
request.getRequestDispatcher("welcome.jsp").forward(request, response);
}
else{
attempts--;
printWriter.println(attempts + " left");
}
if(email.equals("Mhamdoon6#gmail.com") && password.equals("pass0011"))
{
System.out.println("Editor's Home");
HttpSession session = request.getSession();
session.setAttribute("Ali", email);
request.setAttribute("email", email);
request.getRequestDispatcher("welcome.jsp").forward(request, response);
}
else{
attempts--;
printWriter.println(attempts + " left");
}
if(email.equals("Mhamdoon12#gmail.com") && password.equals("pass00901"))
{
System.out.println("User's Home");
HttpSession session = request.getSession();
session.setAttribute("Adam", email);
request.setAttribute("email", email);
request.getRequestDispatcher("welcome.jsp").forward(request, response);
}
else{
attempts--;
printWriter.println(attempts + " left");
}
// if()
// {
// System.out.println("Error message = Invalid info");
// request.setAttribute("errMessage", er);
//
// request.getRequestDispatcher("fail.jsp").forward(request, response);
// }
}
catch (IOException e1)
{
e1.printStackTrace();
}
catch (Exception e2)
{
e2.printStackTrace();
}
}
public void destroy() {
}
}
The easiest way, as your example is simple (string literals checking), is keeping the attempts in the session. This way the attempts are tied up to the session (in other words, to the browser's cookies).
To set the values in the session:
request.getSession().setAttribute("loginAttempts", 3);
request.getSession().setAttribute("lastLoginAttempt", LocalDateTime.now());
To read them:
Integer attempts = (Integer) request.getSession().getAttribute("loginAttempts");
LocalDateTime lastLoginAttempt = (LocalDateTime) request.getSession().getAttribute("lastLoginAttempt");
Now you just have to play with the values, recalculate, and reset them after a successful login. The variables will be kept as long as the browser session is kept.
TL;DR;
I see that everyone who ends up here may need a bit of a briefing about requests and sessions.
You have to understand that the piece of code that goes inside de doGet or doPost is executed every time you enter the url in the browser (The int attempts = 3; from your original post is executed every time, so it will always be 3).
The server collects all the data that comes from the client's browser request and builds a brand new HttpServletRequest object that contains all the data (url, request params, cookies, ip, port, etc.) every time. Press f5? everything gets executed again with a brand new HttpServletRequest.
The way the servers use to keep a conversational state between the server and the client (browser) is through the Session. The Session is the only thing that is kept between requests. You can save variables in the Session for later (like the attempts and the lastLoginAttempt), and rely on the Session to see if a user is successfully logged in.
And how do the server keeps the session between requests if everything gets recreated in each request? through the session cookie. The server users a normal cookie to which it gives a special value (In the Servlet specification this cookie is JSESSIONID). When a request come without that cookie the server creates one giving it the value of a unique identifier. Next requests from the same browser will have that cookie, and the server will use the cookie to attach the session to every HttpServletRequest generated from requests from that browser. So in the brand new HttpServletRequest that is created in every request, the server injects into it the same HttpSession that was being used by the same JSESSIONID.
I searched a lot of resources but none was appropriate to my problem.I am working on single page application (SPA) project ,and I want a logged in user to stay logged in whenever he refreshes the page but without routing.
I have tried to call session authentication servlet in the main controller of the page(this servlet checks whether the session exists or not),but it did not work.
Note: The session is created once the user log in or sing up.
Here is SessionAuthServlet.java:
HttpSession session = request.getSession(true);
User u=(User) session.getAttribute("usersession");
try{
response.setContentType("application/json; charset=UTF-8");
PrintWriter out = response.getWriter();
if(u != null)
{
out.println("{\"+success+\"}");
out.close();
}
else
{
out.println("{ \"result\": \"fail\"}");
out.close();
}
}catch (IOException e) {
e.printStackTrace();
}
MainController in HTML single page application:
appvar.controller('MianController',['$scope','$http','$rootScope',function($scope, $http,$rootScope) {
$rootScope.sessionvalid=function(){
$http.get("http://localhost:8080/MyProject/SessionAuthServlet")
.success(function(response) {
if (response.result=="fail")
{
//***Show the view for not logged user
}
//***Show the view for logged user
}
$rootScope.sessionvalid();
});
}
}]);
Any ideas how to deal with this?
Please guide me
Thanks
Here is how you can stay logged after page refresh without using routing.
You will need below three things
A angular service to hold user information and if he is authenticated or not.
A window sessionstorage to save user information. Even if the page is refereshed the user information will persist in sessionstorage
An interceptor to set request and response.
Service code -
app.service('AuthenticationService', function() {
var auth = {
isLogged: false,
email:"",
isAdmin:false
}
return auth;
});
In your MainController, once user is logged in set the Service AuthenticationService.isLogged = true and $window.sessionStorage = userInfo
Interceptor code-
app.service('TokenInterceptor', function ($q, $window, $location, AuthenticationService) {
return {
request: function (config) {
config.headers = config.headers || {};
if ($window.sessionStorage.token) {
config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
}
return config;
},
/* Set Authentication.isAuthenticated to true if 200 received */
response: function (response) {
if (response != null && response.status == 200 && $window.sessionStorage.token && !AuthenticationService.isAuthenticated) {
AuthenticationService.isAuthenticated = true;
}
return response || $q.when(response);
}
};
});
and in your app.config block add this -
app.config(function($httpProvider){
$httpProvider.interceptors.push(TokenInterceptor);
})
Now your AuthenticationService.isLogged will remain true even if the page is refershed and you can get the logged in user info in the service.
I am doing a rest app in spring and i have a log out method like below. I dont have knowledge on spring so i just searched around and made this.
#RestController
public class LogoutController {
#Autowired
private DatabaseService databaseService;
#RequestMapping(value = "/myApp/user/logout", method = GET, produces = {"application/xml"})
public Users performLogout(#RequestHeader("AuthenticationID") String authID, HttpServletRequest request) throws DatatypeConfigurationException {
return handleLogout(request, authID);
}
private Users handleLogout(HttpServletRequest request, String authID) throws DatatypeConfigurationException {
LogService.info(this.getClass().getName(), "Received Logout Request");
final UsersXMLBuilder usersXMLBuilder = new UsersXMLBuilder();
Users usersXML = usersXMLBuilder.buildDefaultUsersTemplate();
HttpSession session = request.getSession();
AppUtilities utils = new AppUtilities();
try {
//Checking with RegEX
if (utils.isValidUUID(authToken)) {
//Get User Login Record from DB By the AuthID and Delete It
//Invalidate The Session
session.invalidate();
LogService.info(this.getClass().getName(), "Session Invaliated");
} else {
LogService.info(this.getClass().getName(), "Invalid AuthID Found. Not a Valid UUID");
usersXML.setResponseCode(-5);
usersXML.setResponseText("User Session is Not Valid");
}
} catch (Exception ex) {
LogService.error(this.getClass().getName(), ex);
usersXML.setResponseCode(-4);
usersXML.setResponseText("Error Occured!");
return usersXML;
} finally {
LogService.info(this.getClass().getName(), "LogOut Process Finished");
}
return usersXML;
}
}
Questions
1- Is it possible i can return a XML message when spring gives white label error page when i pass no authentication ID in request.
2- How can i get the Authentication Header and check it for null and give message that AuthID is missing.
3- How can i set a attribute explicitly and check for it in every controller that if it exists or not.
4- I plan to have a table where i can store user login time and give a session 10 mins time and Update it more 10 mins if i get any request from the user with the AuthID. So can i have a class or method which can check any incoming request? so i can detect the AuthID and Update My table.
Thank you for your time and help.
You can use an interceptor for that : http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-handlermapping-interceptor
The interceptor will run for every request. It can stop the request and do a response itself.
I am creating a Spring MVC web application using spring security for authentication.
My application has a requirement that the user is logged in automatically when the user accesses a particular URL, say http://www.example.com/login?username=xyz
The user xyz is in the database, and I need to create a session for this user automatically.
Request you to let me know how this can be achieved.
Thanks!
You can do something like this, the idea would be to retrieve the user from the database, make the checks you want and then use the UsernamePasswordAuthenticationToken to create a new Principal into the current session.
The use of the returned Principal of the method is for subsequent uses on the same request, as the Principal won't be available to be retrieved by normal means until the next request.
public Principal doAutoLogin(String username, String password, HttpServletRequest hreq, HttpServletResponse hres, boolean rememberMe) {
User user = getUserFromDatabase(username);
if(user != null && passwordsMatch(password, user.getPassword())) {
try {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
token.setDetails(new WebAuthenticationDetails(hreq));
if(LOG.isDebugEnabled())
LOG.debug("Logging in with "+ token.getPrincipal());
SecurityContextHolder.getContext().setAuthentication(token);
if(rememberMe) {
rememberMeServices.onLoginSuccess(hreq, hres, token);
}
return token;
} catch (Exception e) {
SecurityContextHolder.getContext().setAuthentication(null);
LOG.error("Failure in autoLogin", e);
return null;
}
}
else {
throw new IllegalArgumentException("The specified credentials can't be found");
}
}
I have a ViewScoped JSF page. There exists an ace:dialog where the user is working in. If the user does not click for two hours, his session becomes automaticly destroyed by tomcat.
If the user send a request after that two hours, I redirect to the login page (because the user is logged out). Problem is that I become an error:
java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed
Is there a way to redirect every request to the login page if the user become logged out?
What happened to my Backing Beans if the session got destroyed?
Thats the way of my redirect if the user is request a subsite and is not logged in:
#PostConstruct
public void initialize() {
logger.debug("Start - " + new Throwable().getStackTrace()[0]);
if (hasReadAccess()) {
FacesContext.getCurrentInstance().getExternalContext().redirect(pPath);
return;
}
logger.debug("End- " + new Throwable().getStackTrace()[0]);
}
That is the way of my code, if the user sends a ajax request, for example using a rowEditListener:
public void rowEditListener(RowEditEvent ev) {
logger.debug("Start - " + new Throwable().getStackTrace()[0]);
if (hasReadAccess()) {
FacesContext.getCurrentInstance().getExternalContext().redirect(pPath);
return;
}
// do something
logger.debug("End - " + new Throwable().getStackTrace()[0]);
}
Thanks!
you can use spring:
public void logout() {
try {
SecurityContextHolder.getContext().setAuthentication(null);
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
FacesContext.getCurrentInstance().getExternalContext()
.redirect(FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath() + "/j_spring_security_logout?faces-redirect=true");
} catch (Exception e) {
}
}