简体   繁体   中英

Spring Boot security custom Login page to different url "/" not working

I have just looked at many examples regarding custom login page and every single example uses the same "/login" path. After so much frustration I finally got the login to work with the default.

I want the login form to be rendered at "/" and not login.

Once authenticated, I want it to go "/home".

I am assuming the POST still goes to the default "/login"?

I have tried both on the POST form "/" (Same as the path of the form with GET) & "/login"

Now when I try to login, it keeps redirecting me back to the same "/" with the form.

Here is the basic API logic again: Default login page should be at "/", Form is posted to "/login", Success Url after login is "/home", "/home" and "/mama" are protected routes. After logout, it should redirect to "/"

I cant get through the app, and not sure if anything is missing, It keeps showing the same form login as if I am not getting through even though the password is clearly okay

Here are the routes as explained in the WebConfigurerAdapter filer:

@Configuration
@EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    UserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.userDetailsService(userDetailsService);

        /*auth.inMemoryAuthentication()
                .withUser("appuser").password("1234").roles("HEAD")
                .and()
                .withUser("Mama").password("Mama").roles("MAMA");*/

    }

    @Override
    /*
    * Now we have learnt the basics of Spring Security & Authrization method is completed.
    * Lets fix Authentication first!
    * Got it to work with hasAuthority & hasAnyAuthority but not with roles, not sure why, but it works atm
    *
    * */
    protected void configure(HttpSecurity http) throws Exception {
        //Disabled for development
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/mama").hasAuthority("MAMA")
                .antMatchers("/home").hasAnyAuthority("HEAD", "MAMA")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                    .loginPage("/").permitAll()
                    .defaultSuccessUrl("/home")
                    .usernameParameter("username")
                    .passwordParameter("password")
                .and()
                .logout()
                    .logoutSuccessUrl("/");
    }

    @Bean
    /*
    * Returning no op password encoder for now, as we are not encoding passwords as no registration
    * implemented for Prototype. We would need to add the users from a separate service. W
    *
    * */
    public PasswordEncoder getPasswordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }

}



//LoginApi:
@RestController
public class LoginApi {

    @RequestMapping("/")
    public String index(){
        return "<form method='POST' action='/login'>" +
                "<div>" +
                "<input type='text' name='username' placeholder='Username: ' />" +
                "</div>" +
                "<div>" +
                "<input type='password' name='password' placeholder='Password: ' />" +
                "</div>" +
                "<div>" +
                "<input type='submit' name='submit' value='Login' />" +
                "</div>" +
                "</form>";
    }

    @RequestMapping("/home")
    public String home(){
        return "Welcome to Home!";
    }

    /*
    * This method can be deleted in the end
    * */
    @RequestMapping("/mama")
    public String roleTest(){
        return "This end point is only for Mama!";
    }

}

For this test, I am not using the database, but I have a working implementation of UserPrincipal and UserDetailsService which works perfectly on the default login setup. Happy to share that code if needed. But at this point, I cant see what could go wrong.

In case someone wants to see the UserDetailsService & UserDetails code, that has been included too:

@Service
public class EmployeeDetailsService implements UserDetailsService {


    @Override
    /*
    * First, we are testing the Employee details service, independent of the Database, just to make sure we have this part working,
    * For the purpose of these prototypes, we wont use password encoder because we are not registering,
    *
    * */
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        if (!username.equals("Mama")){
            throw new UsernameNotFoundException("You got the wrong Username, should be mama");
        }

        Employee employee = new Employee();
        Role role = new Role();
        role.setName("HEAD");
        employee
                .setUsername(username)
                .setPassword("1234")
                .setRole(role);

        return new EmployeePrincipal(employee);

    }
}

public class EmployeePrincipal implements UserDetails {

    private Employee employee;


    public EmployeePrincipal(Employee employee){
        this.employee = employee;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
        authorities.add(new SimpleGrantedAuthority(employee.getRole().getName()));
        return  authorities;
    }

    @Override
    public String getPassword() {
        return employee.getPassword();
    }

    @Override
    public String getUsername() {
        return employee.getUsername();
    }

    /*
    * Methods below are the rubbish methods, we keep as true for now
    *
    * */
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

See image attached from Networking, I am not understanding what is happening? The POST request is getting a 302 redirect back to "/" with a 200 status code?

This is happening regardless of weather the credentials are right or wrong

在此处输入图像描述

Any advice would be appreciated

CSRF needs to be implemented with a custom form, so for testing and in dev, its best to disable CSRF

protected void configure(HttpSecurity http) throws Exception {
        //Disabled for development
        http.authorizeRequests()
                .antMatchers("/mama").hasAuthority("MAMA")
                .antMatchers("/home").hasAnyAuthority("HEAD", "MAMA")
                .anyRequest().authenticated()
                .and()
                .csrf().disable()
                .formLogin()
                    .loginPage("/").permitAll()
                    .loginProcessingUrl("/login")
                    .defaultSuccessUrl("/home")
                .and()
                .logout()
                    .logoutSuccessUrl("/");
    }

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