Spring security authorization not working

  Kiến thức lập trình

I created a pure Spring web application for learning purposes. It uses a simple database, where there are two roles: “Admin” and “User”. It has a /login part where I can log in. Based on the role the user is forwarded to different pages. With “User” role it is a simple greeting page where the user can logout, and that’s it. With “Admin” role the user get a list of all the users and he can edit or delete them, or create a new user. The adding and editing happens with using the same form and it is at /add_or_edit, this is used by its controller.

The goal would be that /add_or_edit is restricted to “Admin” usage only. Right now I can reach it without logging in, and also with “User” role. I could use a simple WebFilter to redirect to /login or user home based on the content of the session but I would like to reach something similar with Spring security authorization. The Spring security logging / authentication seems to work fine but I wasn’t able to create a good one for authorization.

I created a SecurityConfig class:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomUserDetailsService userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(NoOpPasswordEncoder.getInstance());
    }

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService);
        authProvider.setPasswordEncoder(NoOpPasswordEncoder.getInstance());
        return authProvider;
    }

    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                    .antMatchers("/add_or_edit", "/add_or_edit/**").hasRole("Admin")
                    .antMatchers("/home","/home/**").hasAnyRole("User", "Admin")
                    .anyRequest().authenticated()
                .and()
                .formLogin()
                    .loginPage("/login")
                    .permitAll()
                .and()
                .logout()
                    .permitAll();
    }
}

It is added to a WebAppInitializer (extends AbstractAnnotationConfigDispatcherServletInitializer) .

Here, at configure I also tried to just prohibit GET and POST before.

For UserDetails I use custom-made wrapper class, this one:

public class CustomUserDetails implements UserDetails {
    private User user;

    public CustomUserDetails(User user) {
        this.user = user;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return user.getRole() == null ?
                Collections.emptyList() :
                Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + user.getRole().getName()));
    }

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

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

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

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

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

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

    public User getUser() {
        return user;
    }
}

The LoginController is this one:

@Controller
public class LoginController {
    private static final Logger logger = LogManager.getLogger(LoginController.class);
    @Autowired
    private AuthenticationManager authenticationManager;

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

    @PostMapping("/login")
    public String handleLogin(@RequestParam("login") String login,
                              @RequestParam("password") String password,
                              HttpSession session) {

        try {
            // Create an Authentication object
            Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(login, password));

            // Authentication successful, set UserDetails in session if needed
            CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
            session.setAttribute(USER, userDetails.getUser());

            // Redirect to home page after successful login
            return "redirect:/home";

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            session.setAttribute("error", "Login or Password is not appropriate. Please try it again.");
            return "login";
        }
    }
}

And this is the CustomUserDetailsService:

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserDao userDao;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userDao.findByLogin(username);
        if (user == null) {
            throw new UsernameNotFoundException("User not found with username: " + username);
        }

        System.out.println("User " + username + " found with role: " + user.getRole().getName());
        CustomUserDetails customUserDetails = new CustomUserDetails(user);
        customUserDetails.getAuthorities().forEach(authority -> {
            System.out.println("Authority: " + authority.getAuthority());
        });
        return new CustomUserDetails(user);
    }
}

Please consider the fact that it is my first attempt to do something like this. I’m 100 percents sure there are many faulty things there. I thought these are maybe enough to find my fault but if I can provide anything that could be useful here, please let me know.

Thank you very much for your help in advance.

Theme wordpress giá rẻ Theme wordpress giá rẻ Thiết kế website

LEAVE A COMMENT