Spring Boot Spring Security Login Redirection Issues - spring-boot

I implemented the Spring Boot Spring Security for handling authentication.
But as soon as I implemented it I keep getting re-directed to the webjars js instead of the welcome page. Here is my code, please suggest what could be the problem.
header.jspf
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fm"%>
<%#taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head>
<title>Life Hacking Tech</title>
<link href="webjars/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="/css/holdings.css"/>
</head>
<body>
login.jsp
<%# include file="common/header.jspf" %>
<%# include file="common/navigation.jspf" %>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<c:set var="contextPath" value="${pageContext.request.contextPath}"/>
<div class="container">
<form method="POST" action="${contextPath}/login" class="form-signin">
<h2 class="form-heading">Log in</h2>
<div class="form-group ${error != null ? 'has-error' : ''}">
<input name="username" type="text" class="form-control" placeholder="Username" autofocus="autofocus"/>
<input name="password" type="password" class="form-control" placeholder="Password"/>
<span>${message}</span>
<span>${error}</span>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<button class="btn btn-lg btn-primary btn-block" type="submit">Log In</button>
<h4 class="text-center">Create an account</h4>
</div>
</form>
</div>
<%# include file="common/footer.jspf" %>
LoginController.java
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(Model model, String error, String logout) {
if (error != null)
model.addAttribute("error", "Your username and password is invalid.");
if (logout != null)
model.addAttribute("message", "You have been logged out successfully.");
return "loginPost";
}
#RequestMapping(value = {"/", "/welcome"}, method = RequestMethod.GET)
public String showPage(ModelMap model) {
model.addAttribute("uname", getLoggedInUserName());
return "welcome";
}
SecurityConfiguration.java
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter{
#Autowired
private UserDetailsService userDetailsService;
#Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/registration").permitAll().anyRequest().authenticated()
.antMatchers("/css/**", "/login").permitAll()
.antMatchers("/","/*todo*/**").authenticated()
.antMatchers("/*holding*/**").authenticated()
.and().formLogin()./*successHandler(authSuccessHandler()).*/loginPage("/login").permitAll()
.and().logout().permitAll()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.and().exceptionHandling()
.accessDeniedPage("/access-denied");
}
#Bean
public AuthenticationSuccessHandler authSuccessHandler(){
return new SimpleUrlAuthenticationSuccessHandler();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
}
After a successful login I get re-directed to the scripts in footer.jsp
footer.jspf
<script src="webjars/jquery/1.9.1/jquery.min.js"></script>
<script src="webjars/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="webjars/bootstrap-datepicker/1.0.1/js/bootstrap-datepicker.js"></script>
<script>
$('#targetDate').datepicker({
})
</script>
<script>
$('.nav li').click(function(e) {
$('.nav li.active').removeClass('active');
var $this = $(this);
if (!$this.hasClass('active')) {
$this.addClass('active');
}
});
</script>
</body>
</html>

I encountered the same issue. Adding
.antMatchers("webjars/**").permitAll()
to the SecurityConfiguration did the trick.

Related

Thymeleaf unable to load static resources

I have a spring web application that loads the templates correctly, but does not load static assets like CSS and images. I have added my static resources within the src/main/resources/static directory, added thymeleaf annotations, added configurations and checked them against similar questions here on StackOverflow, but none of my CSS/image files are getting loaded:
Console Error
Refused to apply style from 'http://localhost:8080/login' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.
Directory Structure
TemplateConfig.java
package com.valencra.recipes.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
#Configuration
public class TemplateConfig {
#Bean
public SpringResourceTemplateResolver templateResolver() {
final SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setPrefix("classpath:/templates/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("LEGACYHTML5");
return templateResolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
final SpringTemplateEngine springTemplateEngine = new SpringTemplateEngine();
springTemplateEngine.addTemplateResolver(templateResolver());
springTemplateEngine.addDialect(new SpringSecurityDialect());
return springTemplateEngine;
}
#Bean
public ThymeleafViewResolver viewResolver() {
final ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
viewResolver.setOrder(1);
return viewResolver;
}
}
layout.html
<!DOCTYPE html>
<html lang="en">
<head th:fragment="head">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>My Recipes</title>
<link href='https://fonts.googleapis.com/css?family=Varela+Round' rel='stylesheet' type='text/css'>
<link rel="stylesheet" th:href="#{/css/unsemantic-grid-responsive.css}">
<link rel="stylesheet" th:href="#{/css/styles.css}">
</head>
<body>
<nav th:fragment="nav">
<a th:href="#{|/profile|}" th:text="${currentUser.name}">
Chandra S.
</a>
•
<form th:action="#{/logout}" method="post" style="display: inline">
logout
</form>
</nav>
<div th:fragment="home">
<div class="grid-100">
<a th:href="#{|/|}">
<h1>
<img th:src="#{/images/chefbot.svg}" height="60px">
<br>
My Recipes
</h1>
</a>
</div>
</div>
<div th:fragment="favorite">
<form th:action="#{|/recipes/${recipe.id}/favorite|}" method="post" style="display:inline">
<button type="submit">
<img th:src="${recipe.isFavorite(currentUser)} ? #{/images/favorited.svg} : #{/images/favorite.svg}" style="height: 15px;">
</button>
</form>
</div>
</body>
</html>
login.html
<!doctype html>
<html lang="en">
<head th:replace="layout :: head"></head>
<body>
<nav>
<a th:href="#{/signup}">
sign-up
</a>
</nav>
<div class="grid-container">
<div th:replace="layout :: home"></div>
<div class="grid-100">
<div class="recipes">
<form th:action="#{|/login|}" method="post" th:object="${user}">
<div class="prefix-20 grid-60 suffix-20">
<p>
<input placeholder="Username" th:field="*{username}"> </input>
</p>
</div> <div class="clear"></div>
<div class="prefix-20 grid-60 suffix-20">
<p>
<input placeholder="Password" type="password" th:field="*{password}"> </input>
</p>
</div> <div class="clear"></div>
<div class="prefix-20 grid-60 suffix-20">
<p>
<button>Login</button>
</p>
</div> <div class="clear"></div>
</form>
</div> <!-- recipes -->
</div> <!-- grid-100 -->
</div> <!-- grid-container -->
</body>
</html>
It looks like your CSS is served as HTML.
Since you put the Stylesheets in src/main/resources/static Spring should set up most things based on sensible defaults, including setting the correct content-type header.
I assume you are using Spring Security, since you showed a login form.
It could be that your resources are protected by Spring Security. Thus instead of your stylesheet you get a 30x redirect to the login page. This would explain why your browser complains about the text/html content type, which is wrong for css but the correct type for a login page.
Do you configure HttpSecurity somewhere in your project (most likely annotated with #EnableWebSecurity)?
If so, you need to allow anonymous access to your resources:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/css/**", "/images/**").permitAll()
// rest of your code
If you switch to the network tab in your browser console, you should be able to inspect the redirect to the login page.
What helped in my case was answer from #phisch and the following code
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler(
"/webjars/**",
"/img/**",
"/css/**",
"/js/**")
.addResourceLocations(
"classpath:/META-INF/resources/webjars/",
"classpath:/static/img/",
"classpath:/static/css/",
"classpath:/static/js/");
}
}

Displaying validation Errors in form with Spring MVC

I've searched through several tutorials and answers to this forum to try to solve my problem: I want to show the validation errors from my bean in my form using spring MVC.
No matter what I try, I can't get it to work. Im not using redirections, my binding results are directly after the model class and so on.
Here's what I have so far:
Login Class:
public class LoginUser implements Serializable {
#NotNull
#Column(name="username", unique=true)
#Size(min=5)
private String username;
#NotNull
#Size(min=5)
private String password;
Login Controller:
#Transactional
#Controller
public class LoginController {
#Autowired
UserDao dao;
#RequestMapping(value = "enter", method = RequestMethod.POST)
public String doLogin(#ModelAttribute("user") #Valid LoginUser user, BindingResult result, HttpSession session) {
if (result.hasErrors()) {
return "login/loginForm";
} else {
if (dao.authenticate(user)) {
session.setAttribute("userLoggedIn", user.getUsername());
return "forward:index";
} else {
return "redirect:login";
}
}
}
Login Form:
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%# taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%# taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<script type="text/javascript" src="resources/js/bootstrap.js"></script>
<script type="text/javascript" src="resources/js/jquery-3.1.0.min.js"></script>
<link rel="stylesheet" href="resources/css/bootstrap.css">
<title><spring:message code="title.login" /></title>
</head>
<body>
<spring:message code="login.message.login" />
<form:form action="enter" commandName="loginForm" method="POST">
<spring:message code="username.login" />
<input type="text" name="username" id="username" /><br />
<form:errors path="username" />
<spring:message code="password.login" />
<input type="password" name="password" id="password" /><br /> <input
type="submit" value="<spring:message code='button.login'/>"><br />
<spring:message code="does.not.have.account.login" />
<spring:message code="register.link.login" />
</form:form>
</body>
</html>
Ohh, I forgot to add - I have a messages.properties configured (working fine, tested) and the messages are comming from there. Here is the line related to the form:
messages_en.Properties
NotEmpty.loginForm.username= Please fill the username field
By the way, it may be worth to note that my view is mounted trough a composite view (made of JSP includes of header, mainpage and footer) that overrides the customary viewloading in Sping-MVC.
You are using RedirectAttributes but you are not redirecting user any where. Try to use "redirect:/<register_path>" or just add Model model to method params and use model.addAtribute("someName", result);
Try below code..
<form:form action="enter" commandName="loginForm" method="POST">
commandName is loginForm so #ModelAttribute("loginForm").
#RequestMapping(value = "enter", method = RequestMethod.POST)
public String doLogin( #Valid #ModelAttribute("loginForm") LoginUser user, BindingResult result, Map<String, Object> model, HttpSession session) {
if (result.hasErrors()) {
return "login/loginForm";
} else {
if (dao.authenticate(user)) {
session.setAttribute("userLoggedIn", user.getUsername());
return "forward:index";
} else {
return "redirect:login";
}
}
}
UPDATE :
You are using NotEmpty.loginForm.username= Please fill the username field which is wrong,It should be NotNull.loginForm.username= Please fill the username field
And also
#NotNull will not validate for empty string..Request from the front end will be "" which is not null.So use #NotEmpty instead.
If you still want to use #NotNull add InitBinder in your controller as shown below
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
}
Then it will validate for empty string.
That is the reason you are getting size error directly and since you have not mentioned any message for that no message is displaying.

Error message not showing in view page in JSR303, using Bootstrap in jsp

I am adding server side validation in my project. and somehow the error message from controller is not reaching view page.
I am using :
spring
jpa,
JSR303 for validation, and
bootstrap
Below is code for add.jsp
<!DOCTYPE html>
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet"
href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<script
src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<style>
.error {
color: #ff0000;
}
.errorblock {
color: #000;
background-color: #ffEEEE;
border: 3px solid #ff0000;
padding: 8px;
margin: 16px;
}
</style>
<title>Add User</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="col-md-4">
<h2>Add User</h2>
<form:form action="user" method="post" role="form"
commandName="user">
<form:errors path="*" cssClass="errorblock" />
<div class="form-group ">
<label for="user">User Name:</label>
<form:input type="text" class="form-control" path="name"
id="name" placeholder="Enter User Name" required="requried"/>
</div>
<div class="form-group">
<label for="email">Email Address:</label>
<form:input type="email" path="emailAddress" class="form-control"
id="email" placeholder="Enter Email Address" required="requried"/>
</div>
<div class="form-group">
<label for="role">Role:</label>
<form:select path="role" class="form-control" id="role" required="requried">
<option disabled selected></option>
<c:forEach var="role" items="${roles}">
<option value="${role.value}">${role.name}</option>
</c:forEach>
</form:select>
</div>
<button type="submit" value="Submit" name="add"
class="btn btn-info active">Submit</button>
Back
</form:form>
</div>
<div class="col-md-4">
<div class="col-md-4"></div>
</div>
</div>
</div>
</div>
</body>
</html>
Below is code for Controller.java
#RequestMapping(value = "/user", params = "add", method = RequestMethod.GET)
public String getAddUser(Model model) {
ArrayList<Role> roles = new ArrayList<Role>();
// From user Add only admin and head of department can be added
roles.add(Role.ADMIN);
roles.add(Role.HEAD_OF_DEPARTMENT);
model.addAttribute("roles", roles);
model.addAttribute("user", new User());
return "user/add";
}
#RequestMapping(value = "/user", params = "add", method = RequestMethod.POST)
public String postAddUser(#ModelAttribute #Valid User user,
BindingResult result) {
if (result.hasErrors()) {
return "redirect:user?add";
} else {
System.out.println("Inside postAddUser");
user = userRepository.save(user);
return "redirect:user?id=" + user.getId();
}
}
Below is code for User.java
package in.ac.jmi.entities;
import in.ac.jmi.constants.Role;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.NotEmpty;
#Entity
#Table(name="USER")
public class User extends UrlEntity{
#Column(name="NAME", nullable = false)
#NotEmpty(message="Name can not be empty")
private String name;
#Column(name="ROLE", nullable = false)
#NotNull(message="Role can not be left blank")
private Role role;
#Column(name = "EMAIL_ADDRESS", nullable = false)
#NotEmpty(message="email address can not be empty")
private String emailAddress;
public User(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
#Override
public String toString() {
return "\nUser [name=" + name + ", role=" + role + ", emailAddress="
+ emailAddress + "]";
}
}
The reason is you are using return "redirect:user?add";, which cleared the error messages in model, try change it to return "user?add";

No mapping found for HTTP request with URI [/resources/css/styles.css] in DispatcherServlet with name 'SpringDispatcher'

I am developing simple web application using Spring MVC. Could you please point me out why the resources are not rendered on the page when I am accessing it? The whole page is being rendered however.
Here my project structure
I am receiving the following warning:
No mapping found for HTTP request with URI [/resources/css/styles.css] in DispatcherServlet with name 'SpringDispatcher'
JSP page that holds the links to the resources:
includes.jsp
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# page contentType="text/html;charset=UTF-8" language="java" %>
<%# taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%# taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<c:set var="base" value="${pageContext.request.contextPath}"/>
<link href="<c:url value="${base}/resources/css/pure/pure-min.css" />" rel="stylesheet">
<link href="<c:url value="${base}/resources/css/styles.css" />" rel="stylesheet">
<link href="<c:url value="${base}/resources/css/menu.css" />" rel="stylesheet">
<script src="${base}/resources/js/validateInput.js"></script>
JSP page that has to be rendered:
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<jsp:include page="/resources/includes.jsp"/>
</head>
<body>
<div id="main-container">
<div class="site-content">
<h1 class="fueling-header">Registration</h1>
<form class="pure-form pure-form-aligned"
action="/register"
method="post"
onsubmit="return validateUserInput();">
</fieldset>
</form>
</div>
</div>
</body>
</html>
Here is my WebAppInitializer code:
public class WebAppContextInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext annotationConfigWebApplicationContext = new AnnotationConfigWebApplicationContext();
annotationConfigWebApplicationContext.register(WebContextConfiguration.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(
"SpringDispatcher",new DispatcherServlet(annotationConfigWebApplicationContext)
);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
ContextConfiguration class
#Configuration
#EnableWebMvc
#Import(ServiceContextConfiguration.class)
#ComponentScan("controllers")
public class WebContextConfiguration {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
#Bean(name = "view_resolver")
public InternalResourceViewResolver internalResourceViewResolver() {
InternalResourceViewResolver internalResourceViewResolver = new InternalResourceViewResolver();
internalResourceViewResolver.setPrefix("/WEB-INF/jsp/");
internalResourceViewResolver.setSuffix(".jsp");
return internalResourceViewResolver;
}
}
And my simple controller
#Controller
public class BasicController {
#RequestMapping(value = "/greeting")
public String sayBasic(Model model){
model.addAttribute("greeting", "Hello world");
return "register";
}
}
The problem was that I had the cyclic reference in another controller i.e. the get method and post were mapped to the same logical view name. My configuration was correct.
For those who will meet the same problem: remove all request mappings and add them step by step till you will see where the problem occurred.
Remove ${base} as it is adding additional / Character.

How to pass variable value from jstl to controller

I have name and password in jsp/jstl
i tried to pass name and password to controller.
this is my controller class
package com.simple.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
#Controller
#RequestMapping("/welcome")
public class HelloController {
private String name;
private String password;
private String user;
#RequestMapping(method = RequestMethod.POST)
public String printWelcome(ModelMap model) {
System.out.println(user);
model.addAttribute(name);
model.addAttribute(password);
model.addAttribute("message", "Spring 3 MVC Hello World");
return "hello";
}
}
this is index.jsp with form tag and c tag libraries
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Registration Page</title>
</head>
<body bgcolor="#999966">
<p> </p>
<form method="POST" action="welcome">
<p><font color="#800000" size="5">
UserName:</font><input type="text" name="name" size="20"></p>
<c:set var="user" value="{param.name}" scope="request">
</c:set>
<p><font color="#800000" size="5">
password:</font><input type="text" name="password" size="20"></p>
<p><input type="submit" value="Submit" name="B1"></p>
</form>
</body>
</html>
i am trying to pass the variable user( the value is taken from the name variable) from this form to controller.
<c:set var="user" value="{param.name}" scope="request">
</c:set>
can any body help me how to do this with c tags..
i have done with using commandName="registereduser" where user is the object of class RegisteredUser.
But i am trying with just passing the variable (with c tags)
I am getting null value for user in sysout
is there any way to do with c tags with the set
thank you..
In your controller:
#Controller
#RequestMapping("/welcome")
public class HelloController {
#RequestMapping(method = RequestMethod.POST)
public String printWelcome(ModelMap model, #RequestParam String name, #RequestParam String password) {
// do something with name & password
model.addAttribute(name);
model.addAttribute(password);
model.addAttribute("message", "Spring 3 MVC Hello World");
return "hello";
}
}
and in your JSP (you have to use a regular HTML form):
<form method="POST" action="welcome">
<table>
<tr>
<td>User Name :</td>
<td><input type="text" id="name" name="name"/></td>
</tr>
<tr>
<td>Password :</td>
<td><input type="password" id="password" name="password"/></td>
</tr>
</table>
<tr>
<td colspan="2"><input type="submit"></td>
</tr>
</table>
</form>
EDIT TO QUESTION (user variable added):
You need to pass user to controller with an input hidden and add another #RequestParam to controller method:
JSP:
<input type="hidden" id="user" name="user" value="${name}"/>
Controller method:
public String printWelcome(ModelMap model, #RequestParam String name,
#RequestParam String password, #RequestParam String user) {
...
I think you can't send user value to server with c tags, you need to submit data (form) to controller.

Resources