How to set the login/logout link visible/invisible with Thymeleaf? - spring-boot

I am a beginner in Spring Framework. I try to make login and logout Thymeleaf pages. Below codes are the Spring Boot login/logout files with Thymeleaf.
First, Login Controllers codes
#Autowired
private HttpSession userSession;
#Autowired
private UserService userService;
#RequestMapping("/users/login")
public String login(LoginForm loginForm) {
return "users/login";
}
#RequestMapping(value="/users/login", method = RequestMethod.POST)
public String loginPage(#Valid LoginForm loginForm, BindingResult bindingResult) {
if(bindingResult.hasErrors()) {
userSession.setAttribute("blogLogin", false);
System.out.println("Wrong Input!!");
return "users/login";
}
if(!userService.authenticate(loginForm.getUsername(), loginForm.getPassword())) {
userSession.setAttribute("blogLogin", false);
System.out.println("login failed!!");
return "users/login";
}
userSession.setAttribute("blogLogin", true);
System.out.println("Login succesfully.");
return "redirect:/";
}
And the layout.html codes using thymeleaf.
<header th:fragment="site-header" th:remove="tag">
<header>
<a href="index.html" th:href="#{/}">
<img src="../public/img/site-logo.png" th:src="#{/img/site-logo.png}" />
</a>
Home
Log in
Log out
Register
Users
Posts
Write Post
<div id="logged-in-info"><span>Hello, <b>(user)</b></span>
<form method="post" th:action="#{/users/logout}">
<input type="submit" value="Log out"/>
</form>
</div>
</header>
</header>
The problem is I have no idea how to make login/logout link toggling codes using th:if statement of thymeleaf. As you know login link and logout link can not be displayed simultaneously.

you can check whether user is authenticated or anonymous like below and can make decisions.
<div sec:authorize="#{isAuthenticated()}">
<a th:href="#{/logout}">Log out</a>
</div>
<div sec:authorize="#{isAnonymous()}">
<a th:href="#{/login}">Log in</a>
</div>

Related

Spring Boot ModelAndView - cannot update value to Model

I am trying to create a form with 3 fields within the class LoginForm: usuario, senha, msgLogin.
I receive the fields usuário and senha from the input boxes and then I try to redirect to the same page with the same fields plus the field MsgLogin. But I've not been able to update the msgLogin field and I don't understand why.
These are the code:
HTML:
<form id="frmLogin" class="form col-md-12" action="#" th:action="#{/login}" th:object="${loginForm}" method="post">
<div class="form-group">
<label for="usuario" class="col-md-1">Usuário: </label>
<input type="text" id="usuario" placeholder="Email" th:field="*{usuario}"/>
</div>
<div class="form-group">
<label for="senha" class="col-md-1">Senha: </label>
<input type="password" id="senha" placeholder="senha" th:field="*{senha}"/>
</div>
<div class="row">
<button id="entrar">Entrar</button>
</div>
<div class="row">
<div id="msgLogin"></div>
<p th:text="${loginForm.msgLogin}" />
</div>
</form>
The Controller:
#RequestMapping("/")
public String init(#ModelAttribute LoginForm loginForm) {
Logger.getAnonymousLogger().info("Tela Inicial.");
return "home";
}
#PostMapping("/login")
public ModelAndView entrar(LoginForm loginForm) throws IOException {
Logger.getAnonymousLogger().info("Entrando no Internet Banking.");
service.login(usuario, senha);
ModelMap model = new ModelMap();
loginForm.setMsgLogin("I want to update that value!");
model.addAttribute("loginForm", loginForm);
return new ModelAndView("redirect:/", model);
}
Class using Lombok:
#Getter
#Setter
public class LoginForm {
private String usuario;
private String senha;
private String msgLogin;
}
A redirect send a 302 HTTP status back to the browser to resubmit using a new url, so it resubmits the same two fields to the new url. There's no expectation of payload data in the 302 response.
In your Controller, change the last line in your entrar method to: return new ModelAndView("/login", model);

Redirect-Spring -MVC - how redirect control to home page?

#RequestMapping(value= "/redirect", method=RequestMethod.GET)
public String redirect()
{
return "redirect:onLogin";
}
how to redirect control back to home page? the above code for retrieving admin home page is not working.
This should work:
#RequestMapping(value= "/redirect", method=RequestMethod.GET)
public String redirect(){
return "redirect:/onLogin";
}
You can also pass parameters on redirect to show Login Failure messages, something like this:
#RequestMapping(value= "/redirect", method=RequestMethod.GET)
public String redirect(){
return "redirect:/onLogin?success=false";
}
And then in your login.jsp
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<c:if test="${param.success eq false}">
<div class="alert alert-danger alert-dismissible">
<button class="close" aria-hidden="true" type="button" data-dismiss="alert">×</button>
<h4><i class="icon fa fa-ban"></i> Login Failed!</h4>
</div>
</c:if>

Thymeleaf with Spring Security - how to check if user is logged in or not?

I'm using Spring Boot with Thymeleaf and Spring Security.
I've got a simple view with a login link. When the user logs in, I'd like to change login link to logout link.
I tried:
<div sec:authorize="#{isAuthenticated()}">
<a th:href="#{/logout}">Log out</a>
</div>
<div sec:authorize="#{isAnonymous()}">
<a th:href="#{/login}">Log in</a>
</div>
but it's not working - it displays both links.
EDIT:
I solved it. I had to register Thymeleaf dialect. In order to do this, I created a new config class, that creates SpringSecurityDialect bean:
#Configuration
public class ThymeleafConfig {
#Bean
public SpringSecurityDialect springSecurityDialect(){
return new SpringSecurityDialect();
}
}
According to thymeleaf docs no spel expression is required. This is not a th: attribute.
So you may try :
<div sec:authorize="isAuthenticated()">
<div sec:authorize="isAnonymous()">
also you can use:
<ul>
<li sec:authorize="isAnonymous()"><a class="nav-link" href="/login">Login</a></li>
<li sec:authorize="isAuthenticated()"><a class="nav-link" href="/logout">Logout</a></li>
<li sec:authorize="isAuthenticated()">Wellcome, <span sec:authentication="name"></span></li>
</ul>
to get de current loged user.
Can also use sec:authorize="isFullyAuthenticated()" which checks if its an anonymousUser and rememberMe.
<div class="button-group" sec:authorize="!isFullyAuthenticated()">
Login
Register
</div>
<div class="button-group" sec:authorize="isFullyAuthenticated()">
Logout
</div>
Following did not work for me for 3.0.4.RELEASE thymeleaf-extras-springsecurity4:
<div sec:authorize="isAnonymous()">
Instead, following worked:
<div th:if="${#authentication == null}">

Strange behavior observed with Spring 3.1 Controller

I'm using Spring 3.1 and tiles to develop a MVC app.
I have a JSP page (header.jsp) and 2 controllers (HomeController and SignupController).
The header.jsp is like this:
<s:url var="login_url" value="${loginUrl}" />
<s:url var="signup_url" value="${signUpFormUrl}" />
<a class="btn btn-primary" href="${login_url}">Login</a>
<a class="btn btn-default" href="${signup_url}">Signup</a>
The HomeController.java is like this (the /login/form URL is configured to be used by spring security as login page):
#Controller
public class HomeController {
#RequestMapping({"/", "/home"})
public String showHomePage(final Map<String, Object> model) {
return "home";
}
#ModelAttribute("loginUrl")
public String getLoginUrl() {
return "/login/form";
}
......
}
The SignupController.java is like this:
#Controller
public class SignupController {
.....
#RequestMapping(value = "/signup/form")
public String signup(#ModelAttribute SignupForm signupForm) {
return "signup/form";
}
#ModelAttribute("signUpFormUrl")
public String getSignUpFormUrl() {
return "/signup/form";
}
.....
}
What's strange is that like it is presented above I got this result when the page is rendered:
<a class="btn btn-primary" href="/appContext/login/form">Login</a>
<a class="btn btn-default" href="">Signup</a>
So the ended up with empty href value.
BUT when I moved around the signup controller code regarding the signup (the RequestMapping and the ModelAttribute method) to the home controller, it worked as expected:
<a class="btn btn-primary" href="/appContext/login/form">Login</a>
<a class="btn btn-default" href="/appContext/signup/form">Signup</a>
Is it possible to use RequestMapping from different Controller inside a same view?
Can someone has a view on what is going on here?
Thanks in advance. I can supply anything other (config?) needed to understand further the problem.

Spring MVC: #RequestParam validation

In my register form i'm using Bean Validator (JSR-303) for validate User object, and need to validate separately password confirmation, because it is not a member of User. I have a problem to assign error message for confirm field. How to do that ?
View:
<form:form modelAttribute="user" method="post" action="register.html">
<div class="fcell">
<div class="clabel"><spring:message code="label.password"/></div>
<div class="cdata"><form:password path="password"/></div>
<div class="cmsgs"><form:errors path="password" /></div>
</div>
<div class="fcell">
<div class="clabel"><spring:message code="label.confirm"/></div>
<div class="cdata"><input type="password" name="confirm"/></div>
<div class="cmsgs"></div>
</div>
</form:form>
Controller:
#RequestMapping("/register.html")
public String register(#RequestParam("confirm") String confirm, #ModelAttribute("user") #Valid User user, BindingResult result) {
if(!DigestUtils.sha256Hex(confirm).equals(user.getPassword())) {
/* Invalid property 'confirm' ... */
result.rejectValue("confirm", "text.passwords_not_equal");
}
return "register";
}
In this case confirmation can be considered a part of model object, like this:
public class RegistrationForm {
#Valid
private User user;
private String confirm;
...
}
...
public String register(#ModelAttribute("user") #Valid RegistrationForm user,
BindingResult result) { ... }
...
<div class="cdata">
<form:password path="confirm"/></div>
<div class="cmsgs"><form:errors path="confirm" />
</div>
...

Resources