Custom login/register form with Spring - fail to redirect user to profile page - spring

I have been working with login and register form with spring and I am stuck a little bit. My login and register form are custom and on same page.
loginRegister.html
<form role="form" action="/app/register" method="post" />
<input type="text" name="firstname" placeholder="First name..." />
<input type="text" name="lastname" placeholder="Last name..." />
<input type="text" name="username" placeholder="Username" />
<input type="text" name="email" placeholder="Email #" />
<input type="text" name="password" placeholder="Password" />
<button type="submit" class="btn">Sign me up!</button>
</form>
<form role="form" action="/app/login" method="post" >
<input type="text" name="username" placeholder="Username..." />
<input type="password" name="password" placeholder="Password..."/>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<button type="submit" class="btn">Sign in!</button>
</form>
HomeController:
#Controller
#Transactional
#RequestMapping({"/", "/homepage"})
public class HomeController {
#RequestMapping(path = "/login", method = RequestMethod.GET)
public String showLoginRegister() {
return "login";
}
#RequestMapping(path="/register", method=RequestMethod.POST)
public String register(User user){
userRepository.save(user);
return "redirect:/users/" + user.getUsername();
}
#RequestMapping(path="/login", method=RequestMethod.POST)
public String login (User user)
{
return "redirect:/users/" + user.getUsername();
}
UserController:
#Controller
#RequestMapping("/users")
public class UserController {
private UserRepository userRepository;
#Autowired
public UserController(UserRepository userRepository){
this.userRepository=userRepository;
}
#RequestMapping(value="/{username}", method = RequestMethod.GET)
public String showUserProfile(#PathVariable String username, Model model){
User user = userRepository.findByUsername(username);
model.addAttribute(user);
return "userProfile";
}
}
When my user registers it should be redirected to profile page, same is after he/she log's in.
My classes for Spring security are:
SecurityWebApplicationInitializer class
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer{
}
SecurityConfig class
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
#Autowired
private DataSource dataSource;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource);
//.passwordEncoder(bcryptEncoder);
}
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.and()
.httpBasic();
http.csrf().disable();
}
}
My problem is that user is never redirected from loginRegister page to profile page.

Update your SecurityConfig file with code:
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/admin").hasRole("ROLE_ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.and()
.httpBasic();
http.csrf().disable();
}

Related

Spring boot http request always handled by the same method

I'm trying to perform the user login functionality in my spring boot application, but it seems that all the http requests are handled by the same method, means that they're redirected into the same URL.
Here is my login controller
package com.lyes.webmail.demo.controllers;
import com.lyes.webmail.demo.DAO.UserDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
#Controller
public class LoginController {
#Autowired
UserDAO asi;
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(){
System.out.println("i'm here"); return "login";
}
#RequestMapping(value = "/connection", method = RequestMethod.POST)
public String logMe(#RequestParam String email, #RequestParam String password){
if(asi.login(email,password)){
System.out.println("success");
return "home";
}else{
System.out.println("failure");
return "error";
}
}
}
my login form
<form id="login-form" class="form" action="/connection" method="POST">
<h3 class="text-center text-info">Login to lyes web mail</h3>
<div class="form-group">
<label for="username" class="text-info">Email:</label><br>
<input type="text" name="email" id="username" class="form-control">
</div>
<div class="form-group">
<label for="password" class="text-info">Password:</label><br>
<input type="text" name="password" id="password" class="form-control">
</div>
<div class="form-group">
<input type="submit" name="submit" class="btn btn-info btn-md" value="Login">
</div>
</form>
And the SecurityConfig which extends the WebSecurityConfigurerAdapter in order to render the login page as the welcome page.
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
System.out.println("lyes");
httpSecurity.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll();
}
}
In the login controller method i've put a sysout to analyse the behaviour, and the message i'm here is printed twice, the first time when the login page loads and the second time when i submit the form.
Any suggestions !??

Spring boot login 302

Why i Cannot login I got always returned status 302 after form submission. Please help me to get rid of this. I need to successfully log in to the service. Help is really appreciated!:)
I have class WebSecurityConfiguration
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Qualifier("userDetailsServiceImpl")
#Autowired
private UserDetailsService userDetailsServiceImpl;
#Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsServiceImpl).passwordEncoder(bCryptPasswordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
//force to use https!
http.requiresChannel()
.requestMatchers(r -> r.getHeader("X-Forwarded-Proto") != null)
.requiresSecure();
//http.csrf().disable();
http
.authorizeRequests()
.antMatchers("/resources/**", "/register").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.successHandler(new RefererRedirectionAuthenticationSuccessHandler())
.loginPage("/user-login")
.permitAll()
.and()
.logout()
.permitAll();
}
/*#Bean
public AuthenticationManager customAuthenticationManager() throws Exception {
return authenticationManager();
}*/
#Bean(name = BeanIds.AUTHENTICATION_MANAGER)
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return authenticationManager();
}
}
Then in the controller i have GET request method
#RequestMapping(value="/user-login", method=RequestMethod.GET)
public String login(Model model, String error, String logout) {
model.addAttribute("login", new Users());
if (error != null)
model.addAttribute("error", "Your username and password are invalid.");
if (logout != null)
model.addAttribute("message", "You have been logged out successfully.");
return "user-login";
}
And then i have user-login.html
<form th:action="#{/login}" th:object="${login}" enctype="application/x-www-form-urlencoded" method="POST">
<p th:text="${message}">Test</p>
<div class="form-group">
<label>Username:</label>
<input type="text" class="form-control" id="username" placeholder="Enter name" name="username" th:field="*{username}"/>
</div>
<div class="form-group">
<label>Password:</label>
<input type="password" class="form-control" id="password" placeholder="Enter password" name="password" th:field="*{password}" />
</div>
<p th:text="${error}">Test</p>
<button class="btn btn-success" type="submit">LOGIN</button>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
<p th:text="${error}">Test</p>
</form>
Likely your CSRF protection is blocking you. Instead of this:
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
Try this (note the th: prefix)
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
Also:
Make sure this is what you want: RefererRedirectionAuthenticationSuccessHandler . It sounds to me like you "want" to redirect after successful login.

spring security login always ends with failure url [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
I have a problem with proper configuration of spring security, registering works well, restricting access works well but when it comes to logging I get always a failure url result, can anyone tell me where the problem is?
Here is my SecurityConfiguration:
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
private DataSource dataSource;
#Value("${spring.queries.users-query}")
private String usersQuery;
#Value("${spring.queries.roles-query}")
private String rolesQuery;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().usersByUsernameQuery(usersQuery).authoritiesByUsernameQuery(rolesQuery)
.dataSource(dataSource).passwordEncoder(bCryptPasswordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/manage/**").hasAuthority("USER").antMatchers("/").permitAll()
.antMatchers("/business_login").permitAll().antMatchers("/business_password_recovery").permitAll()
.antMatchers("/business_register").permitAll().anyRequest().authenticated().and().csrf().disable()
.formLogin().loginPage("/business_login").defaultSuccessUrl("/manage")
.loginProcessingUrl("/process_business_login").usernameParameter("username").passwordParameter("password")
.failureUrl("/business_login").usernameParameter("email").passwordParameter("password").and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/").and()
.exceptionHandling().accessDeniedPage("/access-denied");
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**", "/templates/**",
"/boomerang/**");
}
}
this is my login form:
<form autocomplete="off" class="form-default" method="POST" role="form" action="/process_business_login">
<div class="row">
<div class="col-12">
<div class="form-group login-form-input">
<input type="text" name="username" placeholder="email"
class="form-control form-control-lg login-form-input">
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="form-group has-feedback">
<input type="password" name="password"
placeholder="password"
class="form-control form-control-lg login-form-input">
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="checkbox danger-checkbox">
<input type="checkbox" id="chkRemember"> <label
class="light-gray-color" for="chkRemember">Remember
me</label>
</div>
</div>
</div>
<button type="submit"
class="btn btn-styled btn-lg btn-block btn-danger mt-4 no-border-radius danger-button-login">LOG
IN</button>
</form>
Right there you can see a part of my application.properties file, here I define queries for spring security, they look like this:
spring.queries.users-query=select email, password, active from business_user where email=?
spring.queries.roles-query=select u.email, r.role from business_user u inner join user_role ur on(u.id_business_user=ur.id_business_user) inner join role r on(ur.id_role=r.id_role) where u.email=?
The login always redirects to failure url site, where do I make a mistake?
Your configuration states
.usernameParameter("email")
but the parameter name from the login form states:
<input type="text" name="username" placeholder="email"
class="form-control form-control-lg login-form-input">
So there is a mismatch. I'm thinking that you want to name your form correctly,
instead of
name="username"
you have
name="email"
or you change your configuration from
.usernameParameter("email")
to
.usernameParameter("username")
or remove it, since .usernameParameter("username") is the default.

Configuring Spring Security To Work With Two Different Login Pages

One of the situations in which we may need two login pages is when we have one page for administrators of an application and a different page for normal users.
Each http element will have a different login page and a different login processing URL
I have got this Spring boot security config for allowing login for multiple page.
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
private static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
#Configuration
#Order(1)
public static class App1ConfigurationAdapter extends WebSecurityConfigurerAdapter {
public App1ConfigurationAdapter() {
super();
}
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
private DataSource dataSource;
#Value("${admin-users-query}")
private String usersQuery;
#Value("${admin-roles-query}")
private String rolesQuery;
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.
jdbcAuthentication()
.usersByUsernameQuery(usersQuery)
.authoritiesByUsernameQuery(rolesQuery)
.dataSource(dataSource)
.passwordEncoder(bCryptPasswordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/admin*")
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/admin/temp/login")
.failureUrl("//admin/temp?error=loginError")
.defaultSuccessUrl("/")
.usernameParameter("email")
.passwordParameter("password")
.permitAll()
.and()
.logout()
.logoutUrl("/admin/temp/logout")
.logoutSuccessUrl("/admin/temp")
.and()
.exceptionHandling()
.accessDeniedPage("/403").and().csrf();
}
}
#Configuration
#Order(2)
public static class App2ConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
private DataSource dataSource;
#Value("${user-users-query}")
private String usersQuery;
#Value("${user-roles-query}")
private String rolesQuery;
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.
jdbcAuthentication()
.usersByUsernameQuery(usersQuery)
.authoritiesByUsernameQuery(rolesQuery)
.dataSource(dataSource)
.passwordEncoder(bCryptPasswordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/user*")
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/user/temp/login")
.failureUrl("/user/temp/?error=loginError")
.defaultSuccessUrl("/user/temp")
.usernameParameter("username")
.passwordParameter("password")
.permitAll()
.and()
.logout()
.logoutUrl("/user/temp/logout")
.logoutSuccessUrl("/user/temp/login")
.and()
.exceptionHandling()enter code here
.accessDeniedPage("/403").and().csrf();
}
}
#Configuration
#Order(3)
public static class guestSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().permitAll();
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring().antMatchers("/js/**", "/js/***", "/js/****");
}
}
Admin login form /admin/temp/login
<form th:action="#{/admin/temp/login}" method="post">
<div class="input-group mb-3">
<span class="input-group-addon"><i class="icon-envelope"></i></span>
<input type="text" class="form-control" placeholder="Email" name="email" data-validation="required" />
</div>
<div class="input-group mb-4">
<span class="input-group-addon"><i class="icon-lock"></i></span>
<input type="password" class="form-control" placeholder="Password" name="password" data-validation="required" />
</div>
<div class="row">
<div class="col-6">
<input type="submit" class="btn btn-primary px-4" value="Login">
</div>
<div class="col-6 text-right">
Forgot password?
</div>
</div>
</form>
User login form /user/temp/login
<form th:action="#{/user/temp/login}" method="post">
<div class="input-group mb-3">
<span class="input-group-addon"><i class="icon-envelope"></i></span>
<input type="text" class="form-control" placeholder="Email" name="username" data-validation="required" />
</div>
<div class="input-group mb-4">
<span class="input-group-addon"><i class="icon-lock"></i></span>
<input type="password" class="form-control" placeholder="Password" name="password" data-validation="required" />
</div>
<div class="row">
<div class="col-6">
<input type="submit" class="btn btn-primary px-4" value="Login">
</div>
<div class="col-6 text-right">
Forgot password?
</div>
</div>
</form>
When I Submit the form I get
**Code: 405
(Method Not Allowed)**
When I use single form the form get submted.
Does anyone has an idea on whats happening her?
As someone already answered you need to add
.loginPage("/login.html")
.loginProcessingUrl("/admin/temp/login")
The default URL where the Spring Login will POST to trigger the authentication process is /login which used to be /j_spring_security_check before Spring Security 4.
By default Spring assumes that URL to validate the credentials is /login. To change it you should set up loginProcessingUrl for both formLogin configurations.
It should be something like:
.formLogin()
.loginPage("/user/temp/login")
.failureUrl("/user/temp/?error=loginError")
.defaultSuccessUrl("/user/temp")
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/user/temp/login") # missing line

FreeMarker template error with csrf

It was necessary in the project to configure authentication with Spring Security + Freemarker. I have login page
<#-- #ftlvariable name="_csrf"
type="org.springframework.security.web.csrf.CsrfToken" -->
<#-- #ftlvariable name="error" type="java.util.Optional<String>" -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Log in</title>
</head>
<body>
<nav role="navigation">
<ul>
<li>Home</li>
</ul>
</nav>
<h1>Log in</h1>
<p>You can use: demo#localhost / demo</p>
<form role="form" action="/login" method="post">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<div>
<label for="email">Email address</label>
<input type="email" name="email" id="email" required autofocus/>
</div>
<div>
<label for="password">Password</label>
<input type="password" name="password" id="password" required/>
</div>
<div>
<label for="remember-me">Remember me</label>
<input type="checkbox" name="remember-me" id="remember-me"/>
</div>
<button type="submit">Sign in</button>
</form>
</body>
</html>
This page is handled by LoginController
#Controller
public class LoginController {
#RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView getLoginPage(#RequestParam Optional<String> error) {
return new ModelAndView("login", "error", error);
}
}
The configuration Spring Security
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
#ComponentScan(basePackages = "projectpackages.janus")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/", "/public/**").permitAll()
.antMatchers("/users/**").hasAuthority("ADMINISTRATOR")
.anyRequest().fullyAuthenticated()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.usernameParameter("email")
.permitAll()
.and()
.logout().logoutUrl("/logout")
.deleteCookies("remember-me")
.logoutSuccessUrl("/")
.permitAll()
.and()
.rememberMe();
}
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
}
When I turn to the login page, freemarker throws an exception
FreeMarker template error:
The following has evaluated to null or missing:
==> _csrf [in template "login.ftl" at line 21, column 34]
----
FTL stack trace ("~" means nesting-related):
- Failed at: ${_csrf.parameterName} [in template "login.ftl" at line 21,
column 32]
----
Help to understand the possible reasons of this error. Search on the Internet did not succeed(

Resources