I'm developing a web app with spring boot. I have used spring boot security.
If I use spring boot default login page, Authentication works as expected
But It doesnt work with custom login page .
I'm getting redirected to login page in case I use custom login page while configuring http endpoint in websecurity.java
Sharing the sample code and my diagnosis below.
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
@EnableJpaRepositories(basePackageClasses = UserRepository.class)
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.authorizeRequests().antMatchers("/resources/**").permitAll()
.anyRequest().authenticated()
.and().formLogin().loginPage("/loginPage")
.permitAll();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(getPasswordEncoder());
}
private PasswordEncoder getPasswordEncoder() {
return new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return true;
}
};
}
}
Controller :
@Controller
@EnableAutoConfiguration
@ComponentScan("com.shopping.service")
public class ShoppingController {
@Autowired
private ShoppingService service;
@RequestMapping("/")
public String index() {
return "";
}
@RequestMapping("/loginPage")
public String welcome(Map<String, Object> model) {
return "login";
}
@RequestMapping(value = "/register")
public String register(Model model) {
model.addAttribute("user", new User());
return "register";
}
@RequestMapping(value = "/submitRegistration", method = RequestMethod.POST)
public String submitRegistration(@ModelAttribute User user) {
User saved = service.save(user);
System.out.println(saved);
return "login";
}
@RequestMapping("/home")
public String home() {
return "home";
}
}
login.html :
<form th:action="@{/loginPage}" method="post" th:object="${object}">
<div class="form-group">
<label for="username">Email address:</label>
<input type="email" name="username" class="form-control" id="username">
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" name="password" class="form-control" id="password">
</div>
<div class="checkbox">
<label><input type="checkbox"> Remember me</label>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<a href="/register" class="btn btn-default">Register</a>
</form>
UserDetailsService for user authentication from Database using crud Repo
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepo;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
Optional<User> optionalUser = userRepo.findByEmail(userName);
optionalUser.orElseThrow(() -> new UsernameNotFoundException("User Name not found"));
UserDetailsImpl userDetails = optionalUser.map(user -> new UserDetailsImpl(user)).get();
return userDetails;
}
}
public class UserDetailsImpl extends User implements UserDetails {
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
public UserDetailsImpl(User user) {
this.setEmail(user.getEmail());
this.setAge(user.getAge());
this.setName(user.getName());
this.setId(user.getId());
this.setPassword(user.getPassword());
}
@Override
public String getPassword() {
return super.getPassword();
}
@Override
public String getUsername() {
return super.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;
}
}
You need to specify the ids/names of the username and the password parameter.
The default values are username
and password
, but you use email
and password
.
You can change the default in your security config:
//...
and().formLogin()
.loginPage("/loginPage")
.usernameParameter("email").passwordParameter("password")
//...
Note that you only need to change the one that is different from the default, I just wanted to show both methods.
EDIT 1
The second error is the form action, it must be the one specified by the loginPage("/loginPage")
method, so in this case: th:action="@{/loginPage}"
Additionally the for attribute of your password label is wrong (must be password
in this case).
I tested this and it works for me now.
EDIT 2
Spring security does not work like you imagine it to work. It intercepts the action URL of the form and redirects you to the page you tried to access before you where logged in. If you want to change this you can use successForwardUrl()
In your example:
//...
and().formLogin()
.loginPage("/loginPage")
.successForwardUrl("/home")
//...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.