Issue
I just want to register a user on my web site using springboot
and thymeleaf
, the problem is that when user clicks on "submit", after filled the registration form to save its credentials, well this operation isn't done and I land on login
page.
I'm sure registration isn't completed because when I try to login it is unsuccessful and both "credentials" and "user" tables are empty.
This is the registration form, I'm saving "user" and "credentials" two different entities :
<form th:action="@{/process_register}" method="post">
<label for="username">Email:</label>
<input type="email" name="username" id="username" required th:field="${credentials.username}"/>
<label for="password">Password:</label>
<input type="password" name="password" id="password" required th:field="${credentials.password}"/>
<label for="name">Nome:</label>
<input type="name" name="name" id="name" th:field="${user.name}" required />
<button type="submit" class="btn btn-primary">Register</button>
<a th:href="@{/login}" href="login.html" > or login</a>
</form>
This is /process_register
controller :
@PostMapping("/process_register")
public String processRegister(@ModelAttribute("credentials")Credentials credentials,@ModelAttribute("user") User user) {
credentials.setUser(user);
credentialService.saveCredentials(credentials);
System.out.println("Ho invocato saveCredentials");
return "login";
}
saveCredentials()
method :
@Transactional
public Credentials saveCredentials(Credentials credentials) {
credentials.setPassword(this.passwordEncoder.encode(credentials.getPassword()));
return this.credentialsRepository.save(credentials);
}
where credentialsRepository extends CrudRepository
.
EDIT : AuthConfiguration :
@Configuration
@EnableWebSecurity
public class AuthConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
DataSource datasource;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// authorization paragraph: qui definiamo chi può accedere a cosa
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/",
"/index",
"/login",
"/collection/*",
"/collections",
"/NFTS",
"/signup_form",
"/register",
"/css/**",
"zzz",
"/images/**").permitAll()
.antMatchers(HttpMethod.POST, "/login", "/register").permitAll()
.antMatchers(HttpMethod.GET, "/admin/**").hasAnyAuthority(ADMIN_ROLE)
.antMatchers(HttpMethod.POST, "/admin/**").hasAnyAuthority(ADMIN_ROLE)
.anyRequest().authenticated()
.and().formLogin()
.loginPage("/login")
.defaultSuccessUrl("/default")
.and().logout()
.logoutUrl("/logout")
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/index")
.invalidateHttpSession(true)
.clearAuthentication(true).permitAll();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication()
//use the autowired datasource to access the saved credentials
.dataSource(this.datasource)
//retrieve username and role
.authoritiesByUsernameQuery("SELECT username, role FROM credentials WHERE username=?")
//retrieve username, password and a boolean flag specifying whether the user is enabled or not (always enabled in our case)
.usersByUsernameQuery("SELECT username, password, 1 as enabled FROM credentials WHERE username=?");
/*auth.inMemoryAuthentication()
.withUser("user1").password(passwordEncoder().encode("user1")).roles("USER")
.and()
.withUser("user2").password(passwordEncoder().encode("user2")).roles("USER")
.and()
.withUser("admin").password(passwordEncoder().encode("admin")).roles("ADMIN_ROLE");*/
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Solution
After looking at github repo: you need to create your controllers with regard to auth filters configured in AuthConfiguration
. Only a few paths are allowed to be accessed by an unauthorized user i.a. /register
and /login
.
Since /process_register
is not whitelisted, then the POST request doesn't reach the controller. It is caugth by the filter and redirected to login page instead.
To fix the issue you can for instance do these:
- Change
@PostMapping("/process_register")
to@PostMapping("/register")
in your controller. - Change
th:action="@{/process_register}"
toth:action="@{/register}"
in your template.
After it's done the registration form should work.
By the way:
You should not use th:field
like this. It is supposed to be used together with form backing bean (th:object
) - please refer to the documentation.
Answered By - Jakub Ch.
Answer Checked By - Pedro (JavaFixing Volunteer)