0

I have been trying to get this configured properly, however I am having some difficulties and I believe it is a small fix that I am not seeing. The default spring security login page works just fine but I can't get the custom html to render. It just reads the get mapping "login" as a String. Any assistance would be greatly appreciated!

1.Security Configuration

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    UserDetailsService myUserDetailsServices;
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailsServices);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable().
        authorizeRequests()
                .antMatchers("/admin").hasRole("ADMIN")
                .antMatchers("/user").hasAnyRole("ADMIN", "USER")
                .antMatchers("/").permitAll()
                .and().formLogin()
                    .loginPage("/login")
                    .permitAll();
    }


    @Bean
    public PasswordEncoder getPasswordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

}

3.Main Controller

@RestController
@CrossOrigin(origins="http://localhost:4200")
public class MainController {

    private UserRepository userRepository;
    private UserDetailsService myUserDetailsServices;

    public MainController(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @GetMapping("/")
    public String home() { return ("<h1>Welcome</h1>");
    }

    @GetMapping("/login")
    public String login() { return ("login");
    }

    @GetMapping("/user")
    public String user() {
        return ("<h1>Welcome User</h1>");
    }

    @GetMapping("/admin")
    public String admin() {
        return ("<h1>Welcome Admin</h1>");
    }

    @GetMapping("/all")
    public @ResponseBody Iterable<User> getAllUsers() {
        // This returns a JSON or XML with the users
        return userRepository.findAll();

4.login.html

<html xmlns:th="http://www.thymeleaf.org" xmlns:tiles="http://www.thymeleaf.org">
<head>
    <title tiles:fragment="title">Login</title>
</head>
<body>
<div tiles:fragment="content">
    <form name="f" th:action="@{/login}" method="post">
        <fieldset>
            <legend>Please Login</legend>
            <div th:if="${param.error}" class="alert alert-error">
                Invalid username and password.
            </div>
            <div th:if="${param.logout}" class="alert alert-success">
                You have been logged out.
            </div>
            <label for="username">Username</label>
            <input type="text" id="username" name="username"/>
            <label for="password">Password</label>
            <input type="password" id="password" name="password"/>
            <div class="form-actions">
                <button type="submit" class="btn">Log in</button>
            </div>
        </fieldset>
    </form>
</div>
</body>
</html>
Ryan
  • 103
  • 2
  • 8
  • Delete the extended `WebMvcConfigurerAdapter` class, it isn't needed and stops spring boot configuring some things. – 123 Apr 03 '20 at 01:59

4 Answers4

0

Your Login page is /login.html not /login

so your configuration should be:

.formLogin().loginPage("/login.html").permitAll()
.loginProcessingUrl("/login")
.defaultSuccessUrl("/index.html",true);

and also the the /login mapping in the controller. remove this from MainController:

 @GetMapping("/login")
    public String login() { return ("login");
    }
bob tang
  • 583
  • 3
  • 12
0

I figured it out. I added this ModelAndView to my main controller class and it fixed it. Thank you for the suggestions though.

    @RequestMapping("/login")
public ModelAndView login () {
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("login");
    return modelAndView;
}
Ryan
  • 103
  • 2
  • 8
  • You could solve it that way but it's better to have seperate controller for views, as `@RestController` is not intended to be used for returning views or you also can use `@Controller` with `@ResponseBody` for RESTfull api methods. – S.Step Apr 03 '20 at 18:59
0

change @RestController to @Controller.

read: Difference between spring @Controller and @RestController annotation

S.Step
  • 441
  • 3
  • 8
0

I believe that it will fix the issue if you just try out.

authorizeRequests()
                .antMatchers("/admin").hasRole("ADMIN")
                .antMatchers("/user").hasAnyRole("ADMIN", "USER")
                .antMatchers("/").permitAll()
                .and()   
                .formLogin().loginPage("/login.html")
                .loginProcessingUrl("/login")
                .defaultSuccessUrl("/index.html",true);

Also, Spring security itself have the mapping url end point /login and if you want to change it then the method loginProcessingUrl helps to change the login path

Amit Mishra
  • 498
  • 5
  • 16