简体   繁体   中英

Spring BOOT security : Custom login page is never authenticating

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM