Spring MVC redirect failed - spring

I wanted to do a login page with Spring MVC + Mybatis, the controllers are as below:
#Controller
public class LoginController {
private final UserService userService;
#Autowired
public LoginController(#Qualifier("userService") UserService userService) {
this.userService = userService;
}
#RequestMapping(value = "/login")
public ModelAndView Login(String username, String password,
ModelAndView mv, HttpSession session) {
User user = userService.login(username, password);
// **This is where problems occured**
if (user != null) {
session.setAttribute("user", user);
mv.setView(new RedirectView("/main"));
} else {
mv.addObject("message","Login failed.");
mv.setViewName("loginForm");
}
return mv; // with correct value, but responses 404 error
}
#RequestMapping(value = "/loginForm")
public String LoginForm() {
return "loginForm";
}
#RequestMapping(value = "/main")
public String Main(Model model) {
return "main";
}
}
I have two jsp files:
/WEB-INF/jsp/loginForm.jsp
/WEB-INF/jsp/main.jsp
Whether I submit the login form correctly or not, there is a 404 error:
HTTP Status 404 - /WEB-INF/jsp/login.jsp
Running in debug mode, the mv was returned with "/main" correctly, so it confused me.
Code below works, but i cant add error message to view anymore.
#RequestMapping(value = "/login")
public String Login(String username, String password, HttpSession session) {
User user = userService.login(username, password);
if (user != null) {
session.setAttribute("user", user);
return "redirect:/main";
} else {
session.setAttribute("message","Login failed");
return "redirect:/loginForm";
}
}

i have face same issue but it's help for me
ModelAndView model = new ModelAndView();
if (user != null) {
session.setAttribute("user", user);
model = new ModelAndView("/main");
} else {
mv.addObject("message","Login failed.");
model = new ModelAndView("/loginForm");
}
return model;

Related

Spring Redirect and delete ModelAttribute

I have a controller:
#GetMapping(value = "/login")
public ModelAndView loginGet (#ModelAttribute(value = "MESSAGE_CUSTOM") String message) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {
return new ModelAndView("/login");
} else {
return new ModelAndView("redirect:/");
}
}
When I do a redirect, in this case the ModelAttribute is redirected too:
http://localhost:8080/?MESSAGE_CUSTOM=
How do I prevent the ModelAttribute from being redirected?
#GetMapping(value = "/login")
public ModelAndView loginGet (#ModelAttribute(value = "MESSAGE_CUSTOM") String message) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {
return new ModelAndView("/login");
} else {
RedirectView redirectView = new RedirectView("/");
redirectView.setExposeModelAttributes(false);
return new ModelAndView(redirectView);
}
}
http
http://localhost:8080/

Correct way to deal with index page - Spring Boot

Correct way to deal with index page - Spring Boot
Im insecure about the fact I have more than one method to serve the index page.
Is the code below correct or is there a better way to serve index, index.html and '/' with a single method?
Should I be dealing with this with the .htaccess file on apache? I dont want to keep mixing these two together.
#Controller
public class MainPage {
#Autowired
private UsuarioProvider usuarioProvider;
#GetMapping("/index")
public ModelAndView listar() {
ModelAndView modelAndView = new ModelAndView("index");
//
try {
Usuario u = usuarioProvider.customUserDetails();
modelAndView.addObject("nomeUsuario", u.getNomeCompleto());
modelAndView.addObject("ultimoAcesso", u.getUltimoAcessoFormatado());
} catch (Exception ex) {
ErrorLogger.log(ex);
}
//
return modelAndView;
}
#GetMapping("/index.html")
public ModelAndView index() {
return listar();
}
#GetMapping("/")
public ModelAndView welcome() {
return listar();
}
}
Yes of cource, #GetMapping value can handle both /, /index and /index.html request paths at the same time.
#Controller
public class MainPage {
private final UsuarioProvider usuarioProvider;
public MainPage(UsuarioProvider usuarioProvider) {
this.usuarioProvider = usuarioProvider;
}
#GetMapping(value = {"/", "/index", "/index.html"})
public ModelAndView index() {
ModelAndView modelAndView = new ModelAndView("index");
try {
Usuario u = usuarioProvider.customUserDetails();
modelAndView.addObject("nomeUsuario", u.getNomeCompleto());
modelAndView.addObject("ultimoAcesso", u.getUltimoAcessoFormatado());
} catch (Exception ex) {
ErrorLogger.log(ex);
}
return modelAndView;
}
}

How to know that a session is expired?

I set values to the session object in the method of a controller after success of login :
#RequestMapping(value = "/", method = RequestMethod.POST)
public ModelAndView processLogin(Model model, HttpServletRequest request, HttpSession session, #RequestParam String login, #RequestParam String pwd) {
if ( utilisateurDao.verifierLoginUser(login) ) {
if ( utilisateurDao.verifierUser(login, pwd) ) {
HashMap<String, String> criteres = new HashMap<String, String>();
criteres.put("user_login", login);
criteres.put("user_passwd", pwd);
List<Utilisateur> users = utilisateurDao.lireParCritere(criteres);
session.setAttribute("user_code", ((Utilisateur)users.get(0)).getUser_code());
session.setAttribute("menu", menuDao.afficherMenuParUtilisateur((Integer)session.getAttribute("user_code"), env, request, session));
criteres.clear();
users.clear();
criteres.put("user_code", String.valueOf(session.getAttribute("user_code")));
users = utilisateurDao.lireParCritere(criteres);
session.setAttribute("user_names", ((Utilisateur)users.get(0)).getNoms());
session.setAttribute("logout_menu", env.getProperty("menu.logout"));
return new ModelAndView("redirect:/accueil");
} else {
ModelAndView modelViewLogin = new ModelAndView("redirect:/");
modelViewLogin.addObject("e", "p").addObject("l", login);
return modelViewLogin;
}
} else {
ModelAndView modelViewLogin = new ModelAndView("redirect:/");
modelViewLogin.addObject("e", "l");
return modelViewLogin;
}
}
Then I opened the app inactive for some minutes. After that I went to the "accueil" path. Then the menu was not shown anymore ! The menu was got from session. So how to know that the session is expired and where is the convenient place to test it ?
By default in spring security session is stored in SessionRegistry.
By using SecurityContext you can get this info in your controller code.
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
If you want to be notified when session has expired or person logged out you can always register listener on SessionDestroyedEvent- documentation.
example:
#Component
public class LogoutListener implements ApplicationListener<SessionDestroyedEvent> {
#Override
public void onApplicationEvent(SessionDestroyedEvent event) {
//do your stuff here
}
}
Its also worth to refer to spring docs for that subject.
You can make a Interceptor,
#Component
public class RequestInterceptor extends HandlerInterceptorAdapter
In this interceptor you can control the HttpServletRequest
and check if obj exists into them and then you can throw to a new SessionExpiredException and catch with #ExceptionMapper (https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc)
#Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
if (request.getSession().getAttribute("user")==null) {
throw new SessionExpiredException();
}
return true;
}
I check like below. I think it might be help.
public boolean isUserLoggedIn(HttpServletRequest request) throws IOException {
SecurityContext securityContext = (SecurityContext) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
if(securityContext != null) {
Authentication authentication = securityContext.getAuthentication();
if(null != authentication && authentication.isAuthenticated() != true)
return false;
else
return true;
} else {
return false;
}
}

Spring social returning wrong user profile

I'm using Spring Social LinkedIn to retrieve user profiles with a custom ConnectController since I want to the user to login and retrieve the profile in one step. The issue is that sometimes the first user in the system is returned instead of the currently logged in user.
Here is my CustomConnectController
#Controller
#RequestMapping("/connect")
public class CustomConnectController extends ConnectController {
#Inject
public CustomConnectController(ConnectionFactoryLocator connectionFactoryLocator,
ConnectionRepository connectionRepository) {
super(connectionFactoryLocator, connectionRepository);
}
#Override
protected String connectView(String providerId) {
return "redirect:/hey/" + providerId + "Connect";
}
#Override
protected String connectedView(String providerId) {
return "redirect:/hey/" + providerId + "Connected";
}
}
and my webcontroller
#Controller
public class WebController {
#Autowired
private LinkedIn linkedin;
#Autowired
private ConnectionRepository repository;
#RequestMapping(value = "/hey/linkedinConnected", method = RequestMethod.GET)
public String linkedinConnected(HttpServletRequest request, Model model, Locale locale) {
if (repository.findConnections("linkedin").isEmpty()
|| !linkedin.isAuthorized()) {
return "redirect:/connect/linkedin";
}
LinkedInProfile userProfile = linkedin.profileOperations().getUserProfile();
return "loggedinpage";
}
#RequestMapping(value = "/hey/linkedinConnect", method = RequestMethod.GET)
public String linkedinConnect(HttpServletRequest request, Model model, Locale locale) {
if (repository.findConnections("linkedin").isEmpty()
|| !linkedin.isAuthorized()) {
return "redirect:/connect/linkedin";
}
LinkedInProfile userProfile = linkedin.profileOperations().getUserProfile();
return "loggedinpage";
}
}
Any ideas of what I'm doing wrong?

Spring Social Facebook Template always return same user

I am using Spring Social 2.0.2.RELEASE to provide social login with Facebook. My problem is that Spring Social always return the same first user when I use FacebookTemplate. Here the example:
```
#Autowired
private Facebook facebook;
#RequestMapping(value = "/facebook/login", method = RequestMethod.GET)
public ModelAndView handleFacebookLogin(HttpServletResponse response) {
//always the same user
User profile = facebook.fetchObject("me", User.class, "id", "name", "link", "email");
return new ModelAndView("redirect:/dashboard");
}
```
I also have a Custom ConnectController:
```
#Controller
#RequestMapping("/connect")
public class CustomConnectController extends ConnectController {
#Autowired
public CustomConnectController(ConnectionFactoryLocator connectionFactoryLocator,
ConnectionRepository connectionRepository) {
super(connectionFactoryLocator, connectionRepository);
}
#Override
protected RedirectView connectionStatusRedirect(String providerId, NativeWebRequest request) {
return new RedirectView("/facebook/login");
}
}
```
If a open two browsers and try to login with different users, it always return the first one. My current solution is just copy the entire ConnectController to my app and change the behaviour. It is terrible and I hope that I am making a big mistake.
I had the same issue and solved the problem by creating this class:
#Configuration
public class UniqueSessionUserID extends SocialConfigurerAdapter {
#Override
public UserIdSource getUserIdSource() {
return new UserIdSource() {
#Override
public String getUserId() {
RequestAttributes request = RequestContextHolder.getRequestAttributes();
String uuid = (String) request.getAttribute("_socialUserUUID", RequestAttributes.SCOPE_SESSION);
if (uuid == null) {
uuid = UUID.randomUUID().toString();
}
request.setAttribute("_socialUserUUID", uuid, RequestAttributes.SCOPE_SESSION);
return uuid;
}
};
}
}
Here is a link where it is explained in more detail why this is necessary:
Spring Social Facebook more than one user

Resources