Spring boot + security - problem z rolami

Odpowiedz Nowy wątek
2018-11-26 09:16
0

Witam,
tworzę w celach naukowych małą aplikację w spring boot i chcę do aplikacji dodać dwie role.

Moja klasa z konfiguracją security wygląda tak :

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers(
                "/registration",
                "/js/**",
                "/css/**",
                "/img/**",
                "/webjars/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .loginPage("/login")
            .permitAll()
            .and().rememberMe().key("uniqueAndSecret").userDetailsService(userService)
            .and()
            .logout()
            .invalidateHttpSession(true)
            .clearAuthentication(true)
            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .logoutSuccessUrl("/login?logout")
            .permitAll();
        http.csrf().disable();
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public DaoAuthenticationProvider authenticationProvider(){
        DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
        auth.setUserDetailsService(userService);
        auth.setPasswordEncoder(passwordEncoder());
        return auth;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProvider());
    }

}

W widoku próbuję zrobić coś takiego jak poniżej jednak to nie działa i wszystko wyświetlane jest każdemu. Czy mógłby mi ktoś podpowiedzieć co tu może być nie tak ?

   <div sec:authorize="hasRole('ROLE_ADMIN')">
            This content is only shown to administrators.
        </div>
        <div sec:authorize="hasRole('ROLE_USER')">
            This content is only shown to users.
        </div>

Pozostało 580 znaków

2018-11-26 09:35
eL
0

A pokaż swoją implementację UserService.

Pozostało 580 znaków

2018-11-26 09:36
0

To jest UserServiceImpl:

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        User user = userRepository.findByEmail(email);
        if (user == null){
            throw new UsernameNotFoundException("Invalid username or password.");
        }
        return new org.springframework.security.core.userdetails.User(user.getEmail(),
            user.getPassword(),
            mapRolesToAuthorities(user.getRoles()));
    }

    public User findByEmail(String email){
        return userRepository.findByEmail(email);
    }

    public User save(UserRegistrationDto registration){
        User user = new User();
        user.setFirstName(registration.getFirstName());
        user.setLastName(registration.getLastName());
        user.setEmail(registration.getEmail());
        user.setPassword(passwordEncoder.encode(registration.getPassword()));
        user.setRoles(Arrays.asList(new Role("ROLE_USER")));
        return userRepository.save(user);
    }

    private Collection<? extends GrantedAuthority> mapRolesToAuthorities(Collection<Role> roles){
        return roles.stream()
            .map(role -> new SimpleGrantedAuthority(role.getName()))
            .collect(Collectors.toList());
    }
}

Pozostało 580 znaków

2018-11-26 09:54
eL
0

Jak się zalogujesz to wszystko wszystkim jest wyświetlane czy nawet bez logowania widzisz te div'y?

Te div'y mam umieszczone w widoku do którego jest się przenoszonym po zalogowaniu. I wszystko jest wszystkim wyświetlane ;/ - pawlo00 2018-11-26 09:58

Pozostało 580 znaków

2018-11-26 10:03
eL
0

A czy taki sposób ewentualnie działa:

sec:authorize="hasAuthority('ADMIN')

EDIT:
Zobacz jeszcze co Ci zwróci:

<div sec:authentication="principal.authorities"></div>

Kiedyś kojarzę że czytałem jak te implementację Spring Security są zaimplementowane i bodajże ta metoda hasRole dodawała przedrostek ROLE_ więc może kwestia jest taka że po prostu gdzieś się to wywala z nazwami roli... Implementacja UserService wygląda okej, podobnie jest z konfigiem więc potestuj jeszcze "hasAuthority('ADMIN') albo "hasRole('ROLE_ADMIN')". Kojarzę że można było również zrobić tak:

<sec:authorize access="hasRole('ROLE_ADMIN')">

Edit:
Rozumiem że taką zależność:

<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity4</artifactId>
    <version>3.0.4.RELEASE</version>
</dependency>

masz dodaną do poma?

edytowany 4x, ostatnio: eL, 2018-11-26 10:13

Pozostało 580 znaków

2018-11-26 10:08
0

Niestety nie, bo też to już testowałem.
Dodatkowo przetestowałem również takie coś jak poniżej. Dodałem to w panelu do logowania, więc napis powinien być nie widoczny, ale wyświetlił się ;/

   <div sec:authorize="isAuthenticated()">
                This content is only shown to authenticated users.
            </div>

Pozostało 580 znaków

2018-11-26 10:16
eL
0
  1. Zależność masz dodaną?
  2. Co zwraca Ci:
    <div sec:authentication="principal.authorities"></div>

Pozostało 580 znaków

2018-11-26 10:19
0
  1. To jest mój plik pom.xml

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>3.3.7-1</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
            <version>4.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>webjars-locator</artifactId>
            <version>0.30</version>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity4</artifactId>
        </dependency>
        <dependency>
            <groupId>nz.net.ultraq.thymeleaf</groupId>
            <artifactId>thymeleaf-layout-dialect</artifactId>
            <version>2.3.0</version>
        </dependency>
    </dependencies>
  2. Tekst się pojawia

Ale co Ci to <div sec:authentication="principal.authorities"></div> zwraca ? Powinno wyświetlić role zalogowanego usera. - eL 2018-11-26 10:25
Ps. Uruchom wszystko w trybie incognito albo pokasuje cookies i cache bo czasami coś starego potrafi się przykleić i trzymać przez jakiś czas. - eL 2018-11-26 10:26
Aaaa, no to w takim razie nic mi nie wyświetliło. - pawlo00 2018-11-26 10:27
Cały czas testuję na trybie incognito - pawlo00 2018-11-26 10:29

Pozostało 580 znaków

2018-11-26 10:30
eL
0

Jeśli nie wyświetliło Ci nic (a powinno wyświetlić listę roli tego usera) to sprawdz w debuggerze co Ci w takim razie zwraca ta linijka:

 mapRolesToAuthorities(user.getRoles()));

Ten user na pewno w bazie ma dodane jakieś role? Sama implementacja metody mapRolesToAuthorities wygląda okej ale może przekazujesz tam pustą kolekcję...
Chociaż z drugiej strony jeśli user nie ma żadnej roli to też bezsensu że security wyświetla mu content dla admina... No ale nic, sprawdź tę metodę aby mieć pewność że security user jest tworzony poprawnie.
Przy okazji zrób clean'a projektu i zbuduj na nowo.

EDIT:
@pawlo00 Pokaż jeszcze początek pliku html jak robisz import tego "sec"

edytowany 3x, ostatnio: eL, 2018-11-26 10:35
Ale gdzie tą linijkę dodać ? - pawlo00 2018-11-26 10:32
Ta linijka jest z Twojego kodu. W metodzie loadUserByUsername tworzysz security usera na podstawie swojego usera z bazy. Tam też wywołujesz tę linijkę więc nigdzie jej nie dodawać tylko w debuggerze sprawdź co Ci zwraca. - eL 2018-11-26 10:33

Pozostało 580 znaków

2018-11-26 10:42
0

To mi zwraca :

user : "User(id=1, firstName=Test, lastname=test, [email protected], password=$2a$10$FndsS43/.pJ1UBEGnexqxH5FxasWif365Fbl56FLBm, roles=[Role(id=2, name=ROLE_USER)])"
I tak jak mówiłeś zrobiłem clean'a - pawlo00 2018-11-26 10:43
Która linijka to Ci zwraca? Bo to wygląda na user z Twojego db - eL 2018-11-26 10:45
Pokaż dokładnie co zwraca ta linijka: mapRolesToAuthorities(user.getRoles())); Możesz to zrobić w debbugerze. Wstaw gdzieś tam na tworzeniu Usera breakpointa a potem zaznacz ten fragment -> PPM -> evaluate expression i zwróci Ci wywołanie dla tego fragmentu. Zobacz czy utworzone są poprawnie nazwy ról. - eL 2018-11-26 10:53
Według powyższego hasAuthority powinno Ci bez problemu działać. Zobacz tylko czy masz Role_Admin czy Admin. Dodatkowo zobacz to: https://stackoverflow.com/a/53373249/5877109 bo tak jak wcześniej Ci pisałem, przedrostek Role jest automatycznie dodawany więc może po prostu gdzieś te nazwy Ci się rozjeżdżają. - eL 2018-11-26 10:55
W bazie danych mam ROLE_USER i ROLE_ADMIN - pawlo00 2018-11-26 10:57

Pozostało 580 znaków

2018-11-26 10:56
0

Tutaj jest screen, może będzie lepiej widać
http://pokazywarka.pl/hoxw6g/

Pokaż pozostałe 8 komentarzy
Ale jakby tak było to i w bazie miał bym złe nazwy, a w bazie mam ROLE_ADMIN i ROLE_USER - pawlo00 2018-11-26 11:43
W bazie masz tak jak sam dodasz. Skoro robisz tak: user.setRoles(Arrays.asList(new Role("ROLE_USER"))); to takie nazwy będziesz miał w bazie. - eL 2018-11-26 11:47
Btw. Robienie coś takiego new Role("ROLE_USER") też jest słabe bo tworzysz nową instancję ROLE_USER. Potem jak robisz inserta usera z taką rolą i ten obiekt roli nie ma żadnego ID to do bazy będzie dodawana nowa rola. Sprawdź to jeszcze ale moim zdaniem dodanie każdego usera powoduje dodanie nowej roli ROLE_USER. Jak chcesz to naprawić to zanim podstawisz tę rolę u tego usera to ją zaciągnij z bazy. Wówczas będziesz miał też ID i hibernate zrobi tam po prostu relacje bez dodawania nowego rekordu do roli. - eL 2018-11-26 11:54
Tak, każde tworzenie nowego usera tworzy również nową rolę ;/ - pawlo00 2018-11-26 11:56
Napisałem Ci przecież jak to poprawić. Zamiast tworzyć nową instancję roli, pobierają ja z bazy danych, np. rolerepository.findByName("ROLE_USER"); Dostajesz rolę i ją podstawiasz. - eL 2018-11-26 11:59

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0