I have configured my Java Spring backend to use in memory authentication but when I do a POST request through my angular2 frontend entering the right username/password in a login form, I always get the following errors:
x POST http://localhost:8080/authenticate 401 () zone.js:1382
x EXCEPTION: Response with status: 401 OK for URL: http://localhost:8080/authenticate core.umd.js:3370
x Uncaught Response {_body: "{"code":401,"message":"Authentication failed","err…reason":"authError","message":"Bad credentials"}}", status: 401, ok: false, statusText: "OK", headers: Headers…} Subscriber.ts:241
I have tried so many different security configurations but nothing seems to work. I may be doing something wrong... here's my code:
SecurityConfiguration.java
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
public static final String REMEMBER_ME_KEY = "rememberme_key";
public SecurityConfig() {
super();
logger.info("loading SecurityConfig ................................................ ");
}
#Autowired
private RestUnauthorizedEntryPoint restAuthenticationEntryPoint;
#Autowired
private AccessDeniedHandler restAccessDeniedHandler;
#Autowired
private AuthenticationSuccessHandler restAuthenticationSuccessHandler;
#Autowired
private AuthenticationFailureHandler restAuthenticationFailureHandler;
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/","/client/**","/systemjs.config.js","/index.html");
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("test").password("test").authorities("ADMIN");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers().disable()
.csrf().disable()
.authorizeRequests()
.antMatchers("/failure").permitAll()
.antMatchers("/api/**").permitAll()
.antMatchers("/users").hasAnyAuthority("ADMIN")
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.accessDeniedHandler(restAccessDeniedHandler)
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/authenticate")
.successHandler(restAuthenticationSuccessHandler)
.failureHandler(restAuthenticationFailureHandler)
.usernameParameter("username")
.passwordParameter("password")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())
.deleteCookies("JSESSIONID")
.permitAll()
.and();
}
}
login.service.ts
#Injectable()
export class LoginService {
constructor(private http: Http) {
console.log('Login service initialized...')
}
loginUser(data) {
var headers = new Headers();
headers.append('Content-type', 'application/json');
return this.http.post('/authenticate', JSON.stringify(data), { headers: headers })
.map(res => res.json());
}
login.component.ts
export class LoginComponent {
username:String;
password:String;
data:any
constructor(private LoginService: LoginService) {
}
loginUser(event) {
this.data = {
username: this.username,
password: this.password
};
this.LoginService.loginUser(this.data).subscribe(data => {
this.username = '';
this.password = '';
});
}
login.html
<form class="container col-md-8" (ngSubmit)="loginUser()" style="margin:15px 15px">
<div class="row">
<div class="form group col-md-2 parent ">
<button type="submit" class="btn btn-warning centerV_element">Log In</button>
</div>
<div class="form group col-md-3 parent" style="margin:3px 3px">
<input type="text" [(ngModel)]="username" name="username" class="form control" placeholder="username">
</div>
<div class="form group col-md-3 parent" style="margin:3px 3px">
<input type="text" [(ngModel)]="password" name="password" class="form control" placeholder="password">
</div>
</div>
</form>
Related
I'm new to Spring security and I'm trying to create a custom login page. My problem is the authentication always failed and I always received the Bad Credentials message eventhough the password was correct, note that I have used BCRyptPasswordEncoder when I am saving the new registered account. Without the custom login and using the default formlogin it works fine
This is my WebSecurityConfig
#EnableWebSecurity
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Bean
public UserDetailsService userDetailsService(){
return new CustomApplicantDetailsService();
}
#Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService());
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception { //login logout
http
.authorizeRequests()
.antMatchers("/resources/**")
.authenticated()
.anyRequest()
.permitAll()
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/loginProcess")
.defaultSuccessUrl("/account")
.usernameParameter("email")
//.successForwardUrl("/account")
.permitAll()
.and()
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutSuccessUrl("/login?logout")
.permitAll();
}}
This is my TemplateController to hanlde the url request. Note that I have tried the GetMapping first with the same line of code as loginProcess and without loginprocessingURL in configure but I received the error method get not supported altho most tutorials works somehow.
#Controller
#RequestMapping("/")
public class TemplateController {
#GetMapping("login")
public String login(){
return "loginStudent"; // logicalname
}
#PostMapping("loginProcess")
public String loginProcess(){
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if(authentication == null ||authentication instanceof AnonymousAuthenticationToken){
return "loginStudent"; // logicalname
}
return "redirect:/account.html"; // redirect to account homepage
}
And here is the form from the "loginStudent.html"
<form th:action="#{/loginProcess}" th:method="post" >
<div th:if="${param.error}">
<p class="text-danger">. [[${session.SPRING_SECURITY_LAST_EXCEPTION.message}]]</p>
</div>
<div th:if="${param.logout}">
<p class="text-warning">You have been logged out.</p>
</div>
<div class="form-group">
<label for="email">E-Mail Adresse:</label>
<input type="email" class="form-control" placeholder="Enter email" id="email" name="username " autofocus="autofocus">
</div>
<div class="form-group">
<label for="password">Passwort:</label>
<input type="password" class="form-control" placeholder="Passwort" id="password" name="password">
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox"> Remember me
</label>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
I am a newbie in spring boot. I'm using basic thymeleaf form login. But when I login it returns "localhost:8080/login?error=true". I don't know why. My username and password in the database are correct. Maybe I must add a new controller with post method? please help me
And here, this is my security config class
protected void configure(HttpSecurity http) throws Exception {
logger.info("-----configure(HttpSecurity http)");
http.authorizeRequests()
.antMatchers("/**").permitAll()
.antMatchers("/user/**").hasAnyRole("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/home")
.permitAll()
.and()
.logout()
.permitAll()
.and().csrf().disable();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
logger.info("-----configureGlobal(AuthenticationManagerBuilder auth)");
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}
login form page
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Login</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h2>Stacked form</h2>
<form th:action="#{/login}" method="post">
<div class="form-group">
<input type="text" name="username" id="username" class="form-control input-lg"
placeholder="UserName" required="true" autofocus="true"/>
</div>
<div class="form-group">
<input type="password" name="password" id="password" class="form-control input-lg"
placeholder="Password" required="true"/>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="remember"> Remember me
</label>
</div>
<a class="btn btn-success" th:href="#{'/register'}" role="button">Register</a>
<button type="submit" class="btn btn-primary">Login</button>
</form>
</div>
</body>
</html>
My controller
#GetMapping("/login")
public String login() {
return "/login";
}
The entity
#Entity(name = "dbo_user")
public class User {
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "user_id")
#Id
private int id;
private String email;
private String password;
private String username;
}
First of all, User class has to implement UserDetails interface like this:
// userdetails methods
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.roles.stream().map(SimpleGrantedAuthority::new).collect(toList());
}
#Override
public String getUsername() {
return this.getEmail();
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
#Transient
private List<String> roles = Arrays.asList("ROLE_USER");
public List<String> getRoles() {
return roles;
}
2nd you need a class that implements UserDetailsService like this:
#Service("customCustomerDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
#Autowired
private CredentialRepository users;
#Override
public UserDetails loadUserByUsername(String email) {
return this.users.findByEmail(email)
.orElseThrow(() -> new UsernameNotFoundException("Username: " + email + " not found"));
}
}
Then you autowire that class into your security config class
#Autowired
CustomUserDetailsService customCustomerDetailsService;
You need to implement DAO DaoAuthenticationProvider in your security config class like this:
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService());
authProvider.setPasswordEncoder(encoder());
return authProvider;
I'm quite sure this question would have been answered on this platform.
Are you using thymeleaf security extras? If so, then you need to have dependency included with maven/gradle and thymeleaf namespaces on the login page.
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
and
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5" lang="en">
I have a login box which is a popup on my site, I am having some issues with configuring spring security and the AJAX call to login and authenticate. I am unsure if I've set it up correctly, I'm currently getting a 401() error and reaching Critical Error of the login.js, which is unauthorized access as it stands and the /user/login method not being called.... ! Just a basic idea of how an AJAX login and authentication process should be handled in spring security would be great, including the security config.
THE HTML
<form onSubmit="login()" id="notifyMe" method="POST" role="form">
div class="form-group">
<div class="controls">
<!-- Field -->
<input type="text" id="username" name="username" placeholder="Enter your username" onfocus="this.placeholder = ''" onblur="this.placeholder = 'Click here to write your username'" class="form-control email srequiredField" />
<input type="password" id="password" name="password" placeholder="Enter your password" onfocus="this.placeholder = ''" onblur="this.placeholder = 'Click here to write your password'" class="form-control email srequiredField" />
<!-- Spinner top left during the submission -->
<i class="fa fa-spinner opacity-0"></i>
<!-- Button -->
<button id="login-btw" class="btn btn-lg submit">LOG IN</button>
<div class="clear"></div>
</div>
</div>
</form>
THE AJAX
function login() {
console.info("Attempting to authenticate");
$.ajax({
type: 'POST',
url: '/user/login',
data: $('#notifyMe').serialize(),
cache: false,
dataType: "json",
contentType: "application/json;charset=utf-8",
beforeSend:function(xhr) {
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
},
crossDomain: false,
success: function (data) {
var response = jQuery.parseJSON(data);
if (response == true) {
$(".message").html('<p class="notify-valid">Logging in...</p>').fadeIn();
window.location.reload();
console.info("Authentication Success!");
}
else {
console.error("Unable to login");
console.log(response);
$(".message").html('<p class="notify-valid">Your log in details are incorrect. Please try again.</p>').fadeIn();
}
},
error: function (data) {
console.error("Critical error");
console.log(data);
}
});
SPRING SECURITY CONFIG
#Configuration
#EnableWebSecurity
public class SpringSecurityConfigurer extends WebSecurityConfigurerAdapter{
//Used in context with custom log in form (no /j_spring_security_check)
#Autowired
private CustomAuthenticationProvider cap;
#Autowired
private AjaxAuthenticationSuccessHandler successHandler;
#Autowired
private AjaxAuthenticationFailureHandler failureHandler;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(cap);
}
#Bean(name = "requestCache")
public RequestCache getRequestCache() {
return new HttpSessionRequestCache();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
//CSS FILES AND IMAGES
.antMatchers("/fonts/**", "/css/**", "/img/**", "/js/**", "/admin/css/**", "/admin/img/**", "/admin/js/**" ).permitAll()
//PAGES FOR ALL PEOPLE
.antMatchers("/user/login", "/", "/user/**", "/register/**").permitAll()
//PAGES FOR ADMIN
.antMatchers("/admin/").access("hasAuthority('ROLE_ADMIN')")
.antMatchers("/admin/**").access("hasAuthority('ROLE_ADMIN')")
//PAGES FOR USERS
.antMatchers("/event/**").access("hasAuthority('ROLE_USER')")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/")
.loginProcessingUrl("/user/login")
.failureHandler(failureHandler)
.successHandler(successHandler)
.and()
.csrf().disable()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/user/logout"))
.logoutSuccessUrl("/")
.and().exceptionHandling().accessDeniedPage("/")
//.authenticationEntryPoint(ajaxEntryPoint);
;
}
}
Response header
pragma: no-cache
date: Sun, 05 Nov 2017 11:08:12 GMT
x-content-type-options: nosniff
x-frame-options: DENY
content-type: application/json;charset=UTF-8
cache-control: no-cache, no-store, max-age=0, must-revalidate
transfer-encoding: chunked
x-xss-protection: 1; mode=block
expires: 0
js console image
I'm finding troubles using HDIV with the tag Spring element: "< form:form >".
First, I'm going to explain the architecture of my application:
I'm using Spring framework 4.1.6, Spring Security 4.0.0 and HDIV 2.1.10.
So far I'm not having errors during the development, nevertheless now I 've found one in a jsp file, when I'm using the form tag from Spring:
<form:form
action="${pageContext.servletContext.contextPath}/newUser"
method="POST" class="form-horizontal" commandName="user">
I obtained this error in the line 34: "< form:form "
java.lang.NullPointerException at
org.hdiv.web.servlet.support.HdivRequestDataValueProcessor.processAction(HdivRequestDataValueProcessor.java:122)
at
org.springframework.web.servlet.tags.form.FormTag.processAction(FormTag.java:479)
at
org.springframework.web.servlet.tags.form.FormTag.resolveAction(FormTag.java:433)
at
org.springframework.web.servlet.tags.form.FormTag.writeTagContent(FormTag.java:349)
at
org.springframework.web.servlet.tags.form.AbstractFormTag.doStartTagInternal(AbstractFormTag.java:84)
at
org.springframework.web.servlet.tags.RequestContextAwareTag.doStartTag(RequestContextAwareTag.java:80)
at
org.apache.jsp.WEB_002dINF.jsp.newUser_jsp._jspx_meth_form_005fform_005f0(newUser_jsp.java:197)
at
org.apache.jsp.WEB_002dINF.jsp.newUser_jsp._jspService(newUser_jsp.java:137)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
and more at.....(if it's necessary, I can provide it)
When I try the same code, but exchanging the tag "< form:form >" for the tag "< form >" It works.
When I examined in detail the code from HDIV:
HdivRequestDataValueProcessor.class
public class HdivRequestDataValueProcessor implements RequestDataValueProcessor
protected LinkUrlProcessor linkUrlProcessor;
protected FormUrlProcessor formUrlProcessor;
if (this.innerRequestDataValueProcessor != null) {
String processedAction = this.innerRequestDataValueProcessor.processAction(request, action, method);
if (processedAction != action) {
action = processedAction;
}
}
String result = this.formUrlProcessor.processUrl(request, action, method);//line 122
return result;
}
I wondered that maybe due to the fact that 'form:form' has a different structure than 'form', HDIV cannot find some parameters such as 'action', 'method'...But I'm not sure.
Also I attached my config files to provide more useful information (Java-based Config):
WebApplicationInit.class
import javax.servlet.Filter;
import javax.servlet.ServletContext;
import org.hdiv.filter.ValidatorFilter;
import org.hdiv.listener.InitListener;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebApplicationInit extends
AbstractAnnotationConfigDispatcherServletInitializer {
// http://www.robinhowlett.com/blog/2013/02/13/spring-app-migration-from-xml-to-java-based-config/
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootConfig.class, DatabaseConfig.class,
SecurityConfig.class, HdivSecurityConfig.class };
// , HdivSecurityConfig.class
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { MvcConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
//web.xml filter
#Override
protected Filter[] getServletFilters(){
return new Filter[] { new ValidatorFilter()};
}
// web.xml listener
#Override
protected void registerDispatcherServlet(ServletContext servletContext) {
super.registerDispatcherServlet(servletContext);
servletContext.addListener(InitListener.class);
}
}
HdivSecurityConfig.class
#Configuration
#EnableHdivWebSecurity
public class HdivSecurityConfig extends HdivWebSecurityConfigurerAdapter {
#Override
public void addExclusions(ExclusionRegistry registry) {
registry.addUrlExclusions("/login").method("GET");
registry.addUrlExclusions("/newUser").method("GET");
registry.addUrlExclusions("/newUser").method("POST");
registry.addUrlExclusions("/about").method("GET");
registry.addUrlExclusions("/resources/.*").method("GET");
registry.addUrlExclusions("/bst-lib/.*").method("GET");
registry.addUrlExclusions("/images/.*").method("GET");
}
#Override
public void configure(SecurityConfigBuilder builder) {
//the session has expired, go to login again
builder.sessionExpired().homePage("/").loginPage("/login");
//Execution strategy
builder.strategy(Strategy.CIPHER);
//error page
builder.errorPage("/error");
}
}
SecurityConfig.class
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DriverManagerDataSource myWebAppDataSource;
#Autowired
private MyWebAppSimpleAuthenticationProvider myWebAppAuthenticationProvider;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)
throws Exception {
auth.authenticationProvider(myWebAppAuthenticationProvider);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/resources/**", "/bst-lib/**", "/images/**",
"/about", "/newUser").permitAll().anyRequest()
.authenticated().and().formLogin().loginPage("/login")
.permitAll();
}
}
SecurityWebApplicationInit.class
public class SecurityWebApplicationInit extends
AbstractSecurityWebApplicationInitializer {}
Thank you in advance!!
Best Regards,
Alberto
----EDIT---
Following the given example, This is now my code:
WebApplicationInit.class
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebApplicationInit extends
AbstractAnnotationConfigDispatcherServletInitializer {
// http://www.robinhowlett.com/blog/2013/02/13/spring-app-migration-from-xml-to-java-based-config/
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { RootConfig.class, DatabaseConfig.class,
SecurityConfig.class, HdivSecurityConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { MvcConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected String getServletName(){
return "myDispatcher";
}
}
HDIVSecurityConfig.class
import org.hdiv.config.Strategy;
import org.hdiv.config.annotation.EnableHdivWebSecurity;
import org.hdiv.config.annotation.ExclusionRegistry;
import org.hdiv.config.annotation.RuleRegistry;
import org.hdiv.config.annotation.ValidationConfigurer;
import org.hdiv.config.annotation.builders.SecurityConfigBuilder;
import org.hdiv.config.annotation.configuration.HdivWebSecurityConfigurerAdapter;
import org.springframework.context.annotation.Configuration;
#Configuration
#EnableHdivWebSecurity
public class HdivSecurityConfig extends HdivWebSecurityConfigurerAdapter {
#Override
public void addExclusions(ExclusionRegistry registry) {
registry.addUrlExclusions("/login").method("GET");
registry.addUrlExclusions("/newUser").method("GET");
registry.addUrlExclusions("/newUser").method("POST");
registry.addUrlExclusions("/about").method("GET");
registry.addUrlExclusions("/resources/.*").method("GET");
registry.addUrlExclusions("/bst-lib/.*").method("GET");
registry.addUrlExclusions("/images/.*").method("GET");
registry.addParamExclusions("_csrf");
}
#Override
public void configure(SecurityConfigBuilder builder) {
// the session has expired, go to login again
builder.sessionExpired().homePage("/").loginPage("/login");
// Execution strategy
builder.strategy(Strategy.MEMORY);
builder.maxPagesPerSession(5);
// error page
builder.errorPage("/error");
}
#Override
public void addRules(RuleRegistry registry) {
//registry.addRule("safeText").acceptedPattern("^[a-zA-Z0-9#.\\-_]*$");
}
#Override
public void configureEditableValidation(
ValidationConfigurer validationConfigurer) {
validationConfigurer.addValidation("/.*");
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>myWebApp</display-name>
<listener>
<listener-class>org.hdiv.listener.InitListener</listener-class>
</listener>
<!-- HDIV Validator Filter -->
<filter>
<filter-name>ValidatorFilter</filter-name>
<filter-class>org.hdiv.filter.ValidatorFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ValidatorFilter</filter-name>
<servlet-name>myDispatcher</servlet-name>
</filter-mapping>
<jsp-config>
<taglib>
<taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/tlds/hdiv-c.tld</taglib-location>
</taglib>
</jsp-config>
</web-app>
newUser.jsp
<form:form
action="${pageContext.servletContext.contextPath}/newUser"
method="POST" class="form-horizontal" commandName="user">
<div class="form-group">
<label for="inputName"
class="col-sm-offset-2 col-sm-2 control-label">Name:</label>
<div class="col-sm-6">
<form:input class="form-control" id="inputName"
placeholder="Name" path="name" />
</div>
</div>
<div class="form-group">
<label for="inputSurname"
class="col-sm-offset-2 col-sm-2 control-label">Surname:</label>
<div class="col-sm-6">
<form:input class="form-control" id="inputSurname"
placeholder="Surname" path="surname" />
</div>
</div>
<div class="form-group">
<label for="inputOrganisation"
class="col-sm-offset-2 col-sm-2 control-label">Organization:</label>
<div class="col-sm-6">
<form:input class="form-control" id="inputOrganisation"
placeholder="Organization" path="organization" />
</div>
</div>
<div class="form-group">
<label for="inputEmail"
class="col-sm-offset-2 col-sm-2 control-label">Email:</label>
<div class="col-sm-6">
<form:input type="email" class="form-control" id="inputEmail"
placeholder="Email" path="email" />
</div>
</div>
<div class="form-group">
<label for="inputPassword"
class="col-sm-offset-2 col-sm-2 control-label">Password:</label>
<div class="col-sm-6">
<form:password class="form-control" id="inputPassword"
placeholder="Password" path="password" />
</div>
</div>
<div class="form-group">
<label for="inputRPassword"
class="col-sm-offset-2 col-sm-2 control-label">Repeat
Password:</label>
<div class="col-sm-6">
<form:password class="form-control" id="inputRPassword"
placeholder="Repeat Password" path="rPassword" />
</div>
</div>
<div class="col-sm-offset-4 col-sm-8">
<button type="submit" class="btn btn-default login-button">Sing
in</button>
<button type="button" class="btn btn-default login-button"
onclick="clearAll()">Clear All</button>
<button type="button" class="btn btn-default login-button"
onclick="comeBack()">Come Back</button>
</div>
<input type="hidden" name="${_csrf.parameterName}"
value="${_csrf.token}" />
</form:form>
MvcConfig.class
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.ec.myWebApp" })
public class MvcConfig extends WebMvcConfigurerAdapter {
#Autowired
/*
* If I use this commented line, The application fails due to the fact that the bean "hdivEditableValidator" can't be found...If I don't use the tag "Qualifier" it does not fail
*/
// #Qualifier("hdivEditableValidator")
private Validator hdivEditableValidator;
// View Name -> View
#Bean
public InternalResourceViewResolver getViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
// static resources
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations(
"/public-resources/");
registry.addResourceHandler("/bst-lib/**").addResourceLocations(
"/public-resources/lib/bootstrap-3.3.2-dist/");
registry.addResourceHandler("/images/**").addResourceLocations(
"/public-resources/images/");
}
#Bean
public MultipartResolver multipartResolver() {
HdivCommonsMultipartResolver resolver = new HdivCommonsMultipartResolver();
resolver.setMaxUploadSize(100000);
return resolver;
}
#Override
public Validator getValidator() {
return hdivEditableValidator;
}
}
I changed the way to add the HDIV to my Web Application, adding it in the xml file, instead of doing that in using java-based configuration. Additionally, I added the Qualifier tag (MvcConfig.class), using the example, but it does not work when I use it...(It can not find the bean...).
The null error hasn't disappeared...
The problem has been solved changing this line:
#ComponentScan(basePackages = { "com.ec.myWebApp" })
in the class: MvcConfing, for this:
#ComponentScan(basePackages = { "com.ec.myWebApp.controllers",
"com.ec.myWebApp.dao", "com.ec.myWebApp.services" })
My original line scanned twice the HDIV config class, first during the context creation and the second one by the "#ComponentScan". This gave place to an incorrect initialization. So, the config package was used twice, instead of once.
Thank you.
I am stuck with this persistent error while creating my spring 4 app. Here's my code:
Initializer.java:
public class Initializer extends AbstractAnnotationConfigDispatcherServletInitializer implements WebApplicationInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
// TODO Auto-generated method stub
return new Class[] { RootConfig.class, SecurityConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
// TODO Auto-generated method stub
return new Class[] { WebAppConfig.class };
}
#Override
protected String[] getServletMappings() {
// TODO Auto-generated method stub
return new String[] { "/" };
}
// I have tried adding the following but it doesn't seem to work also:
#Override
protected Filter[] getServletFilters() {
// TODO Auto-generated method stub
return new Filter[] { new DelegatingFilterProxy("springSecurityFilterChain") };
}
}
WebAppConfig.java:
#Configuration
#EnableWebMvc
#ComponentScan("com.myco.controller")
public class WebAppConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/pages/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
}
RootConfig.java:
#Configuration
#EnableTransactionManagement
#ComponentScan("com.mycompany")
#PropertySource("classpath:application.properties")
public class RootConfig {
private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";
private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";
#Resource
private Environment env;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
return dataSource;
}
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setPackagesToScan(env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
sessionFactoryBean.setHibernateProperties(hibProperties());
return sessionFactoryBean;
}
private Properties hibProperties() {
Properties properties = new Properties();
properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
return properties;
}
#Bean
public HibernateTransactionManager transactionManager() {
HibernateTransactionManager transactionManager = new HibernateTransactionManager();
transactionManager.setSessionFactory(sessionFactory().getObject());
return transactionManager;
}
}
SecurityConfig.java:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private DataSource dataSource;
#Autowired
private UserDetailsService userDetailsService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().userDetailsService(userDetailsService)
.authorizeRequests()
.antMatchers("/sec/moderation.html").hasRole("MODERATOR")
.antMatchers("/admin/**").hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/user-login.html")
.defaultSuccessUrl("/success-login.html")
.failureUrl("/error-login.html")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/index.html");
}
}
And lastly, my login jsp (login-form.jsp):
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%#taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Login page</title>
<style>
.error {
color: red;
}
</style>
</head>
<body>
<h1>Login page</h1>
<p>
<c:if test="${error == true}">
<b class="error">Invalid login or password.</b>
</c:if>
</p>
<form method="post" action="<c:url value='j_spring_security_check'/>" >
<table>
<tbody>
<tr>
<td>Login:</td>
<td><input type="text" name="j_username" id="j_username"size="30" maxlength="40" /></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" name="j_password" id="j_password" size="30" maxlength="32" /></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Login" /></td>
</tr>
</tbody>
</table>
</form>
<p>
Home page<br/>
</p>
</body>
</html>
My error:
If you are using Spring Security 3.2 the login url is changed to /login from /j_spring_security_check also the username and password paremeters are changed.
username : from j_username to username
password : from j_password to password
So your form will be.
<form method="post" action="<c:url value='login'/>" >
<table>
<tbody>
<tr>
<td>Login:</td>
<td><input type="text" name="username" id="username"size="30" maxlength="40" /></td>
</tr>
<tr>
<td>Password:</td>
<td><input type="password" name="password" id="password" size="30" maxlength="32" /></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Login" /></td>
</tr>
</tbody>
</table>
</form>