Spring Security - zabezpieczanie poszczególnych kontrolerów lub akcji

0

//EDIT: przepraszam format kodu
Hej, mam taki kawałek standardowego kodu jeśli chodzi o security. Chciałbym zabezpieczyć kontrolery lub/i akcje uwzględniając role.
Mechanizm dodawania userów i przypisywania ról już mam. Bez tego w tej chwili do aplikacji loguję się ale nie uwzględniam ról. Jak zabezpieczyć poszczególne strony?

@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers().disable()
.csrf().disable()
.authorizeRequests()
// apps css fonts global js layouts pages
.antMatchers("/", "/registration",
"/css/", "/js/", "/images/", "/fonts/", "/assets/",
"/apps/", "/global/*", "/layouts/", "/pages/", "/assets/font-awesome/").permitAll()
.anyRequest().authenticated()
.and()
.formLogin() //login configuration
.loginPage("/")
.permitAll()
.loginProcessingUrl("/login")
.usernameParameter("form-email")
.passwordParameter("form-password")
.defaultSuccessUrl("/login")
.and()
.logout() //logout configuration
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.and()
.rememberMe() // Remember me config ...
.and();
}
1

Najprościej to do metod/kontrolerów dodać @Secured("ROLE") i powinno śmigać.

0

ewentualnie jeśli chcesz w konfiguracji to hasRole("ROLE")

0

ok rozumiem,
fajnie to działa np.

.antMatchers("/user/**").hasRole("ADMIN")

Teraz gdy wchodzę pod taki url dostaję 403 i powinienem stworzyć jakiś custom 403 ( zaraz poczytam )
Ale jak zrobić np. logout jeśli nie mam uprawnień?

0

czy można jakoś ładniej zrobić tą 403 niż tutaj
http://stackoverflow.com/questions/24194724/custom-403-error-page-with-spring-security-configured-via-java-code

tak zrobiłem 404

@Controller
public class AppErrorController implements ErrorController {

  private final static String ERROR_PATH = "/error";

  @Value("${debug}")
  private boolean debug;

  @Autowired
  private ErrorAttributes errorAttributes;

  @RequestMapping(ERROR_PATH)
  public Model showError(HttpServletRequest request, HttpServletResponse response) {
    return new Model("/error/404_page")
      .addObject("error", new Error(response.getStatus(), getErrorAttributes(request, debug)));
  }

  @Override
  public String getErrorPath() {
    return ERROR_PATH;
  }


  private Map<String, Object> getErrorAttributes(HttpServletRequest request, boolean includeStackTrace) {
    RequestAttributes requestAttributes = new ServletRequestAttributes(request);
    return errorAttributes.getErrorAttributes(requestAttributes, includeStackTrace);
  }
}
0

a guzik jednak działa.
próbowałem hasRole(), hasAuthority()
role z przedrostkiem ROLE_nazwaRoli i bez

nawet gdy user ma zadaną role dostaję 403. Czy coś trzeba jeszcze podkofigurować?

0

W jaki sposób nadajesz użytkownikom role ? Może dany user wcale nie ma określonej roli, tylko Tobie się wydaje że ma ? Możesz też pobrać userinfo debuggerem i sprawdzić jaką rolę ma.

0

mam trzy tabele: users, roles, user_roles.
User_roles: user_id, role_id
Mam miejsce w aplikacji gdzie dodaję usera i przypisuje do niego role ( mam ich aż trzy ;) )

0

do widoku przekazałem sobie

 SecurityContextHolder.getContext().getAuthentication().getAuthorities();

i dostaję ROLE_USER
moje role w tabeli to: ADMIN, TESTER, PLANNER

oznacza to, że muszę jakoś to spiąć

0

już to rozpoznałem ale nie rozwiązałem, otóż:
mam klasę i potrzebne jest poprawnę zwócenie ról przypisanych do usera i przypisanie do authorities. Tak jak jest teraz się kompiluje ale gdy uruchamiam aplikacje po zalogowaniu dostaję failed to lazily initialize a collection of role: nl.vuurin.user.entities.Member.roles, could not initialize proxy - no Session

 public class UserDetailsImpl implements UserDetails {

  @Autowired
  RoleRepository roleRepository;

  @Autowired
  MemberRepository memberRepository;

	private Member member;

	public Member getMember() {
		return member;
	}

	public void setMember(Member member) {
		this.member = member;
	}

	public UserDetailsImpl(Member member) {
		this.member = member;
	}

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {

		Collection<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();

    // tutaj potrzebuję wyciągnąć role przypisane do usera i zapakować to authorities.
    Set<Role> roles = member.getRoles();
    for(Role r : roles) {
      authorities.add(new SimpleGrantedAuthority(r.getName()));
    }
		//authorities.add(new SimpleGrantedAuthority("ADMIN")); // hardcoded i chodzi, tutaj miałem na sztywno ROLE_USER i zapomnialem o tym 
		//authorities.add(new SimpleGrantedAuthority("test")); // // hardcoded i chodzi 

		return authorities;

	}

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

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

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

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

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

	@Override
	public boolean isEnabled() {
    return member.getEnabled();
	}
}
0

A teraz napisz to porządnie, bo masz niepotrzebne repozytoria. W dodatku można to zrobić bez potrzeby ręcznego przepisywania wartości. Na przykład JPQLem:

TypedQuery<GrantedAuthority> q = em.createQuery("SELECT NEW org.springframework.security.core.GrantedAuthority(r.name) FROM Member m JOIN m.role r WHERE m.name = :name", GrantedAuthority.class);
q.setParameter("name", member.getName());
return q.getResultList();
0

nie rozumiem do końca tego kodu. To mój 1szy projekt w Spring Boot.
Próbowałem JPQLem w repozytorium Role w stylu

 @Query("select r.name from Role r inner join r.memberRole rm where rm.memberId = :memberId")
List<Role> FindMemberRoles(@Param("memberId") Long memberId);

to nie działa, próbowałem tak dlatego, że mam tabelę łączącą role_id, user_id, która powstaje a nie jest encją samą w sobie.

0

Ale w tym przypadku wybierasz r.name co zapewne jest Stringiem, ale metoda zwraca listę typu Role. Zamień na List<String> i powinno śmigać. Moje zapytanie bazowało na teoretycznym modelu, gdzie rola nie wie do kogo należy.

0

zrobiłem dokładnie tak
w RoleRepository

   @Query("select r.name from Role r inner join r.memberRole rm where rm.memberId = :memberId")
  List<String> findMemberRoles(@Param("memberId") Long memberId);

i metoda getAuthorities

 	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {

		Collection<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();

    List<String> roles = roleRepository.findMemberRoles(this.member.getId());
    for(String role : roles){
      authorities.add(new SimpleGrantedAuthority(role));
    }
		return authorities;

	}

i przy kompilacji strzela we mnie
Caused by: org.hibernate.QueryException: could not resolve property: memberRole of: user.entities.Role [select r.name from user.entities.Role r inner join r.memberRole rm where rm.memberId = :memberId]

0

Role, prosta encja

0

Niby prosta, ale nie ma pola memberRole (albo jest inna nazwa).

0

przepraszam usuń proszę mój powyższy błąd
Role, prosta encja

 @Entity
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Getter
    private Long id;

    @NotNull
    @Getter
    private String name;

    @ManyToMany(mappedBy = "roles")
    private Set<Member> members;
}

i member

 @Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String firstName;
    private String lastName;

    @Email
    @NotNull
    private String email;

    private String password;

    private boolean enabled;

    @Transient
    private String passwordConfirm;

    @ManyToMany
    @JoinTable(name = "member_role",
      joinColumns = @JoinColumn(name = "member_id"),
      inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Set<Role> roles;

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }
    public boolean getEnabled() {
      return enabled;
    }
}
0

z tych encji gdy zapuszczam aplikację generują sie trzy tabele: member, role, member_role ( member_id, role_id )

0

I teraz jasne, bo próbujesz wybrać wszystkie role użytkownika o danym ID, ale robiąc jakąś dziwną konstrukcję, która zaczyna od roli.

SELECT r.name FROM Member m JOIN Role r WHERE m.id = :memberId

i można jeszcze dodać to NEW ..., które wyprodukuje jakiś konkretny springowy obiekt na podstawie nazwy roli.

0

tak, potrzebuję wybrać wszystkie role usera o danym ID.
w tej chwili mam tak

   @Query("SELECT r.name FROM Member m JOIN Role r WHERE m.id = :memberId")
  List<String> findMemberRoles(@Param("memberId") Long memberId);

i otrzymuję
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Path expected for join! [SELECT r.name FROM user.entities.Member m JOIN Role r WHERE m.id = :memberId]

0

Ok mam, JOIN FETCH m.role WHERE... coś w ten deseń, ale piszę z pamięci :)

0

dałem tak

   @Query("SELECT r.name FROM Member m JOIN FETCH m.Role r WHERE m.id = :memberId")

Caused by: org.hibernate.QueryException: could not resolve property: Role of: nl.vuurin.user.entities.Member

0

Jakbys mogl w wolnej chwili w to spojrzec bylbym wdzieczny

0

próbuje jeszcze tak ale zupełnie nie rozumiem dlaczego findOne(id) dostaję NullPointerException
cała klasa

 package pl.project.user.service.impl;

import pl.project.user.entities.Member;
import pl.project.user.repository.MemberRepository;
import pl.project.user.repository.RoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.HashSet;

public class UserDetailsImpl implements UserDetails {

  @Autowired
  RoleRepository roleRepository;

  @Autowired
  MemberRepository memberRepository;

	private Member member;

	public Member getMember() {
		return member;
	}

	public void setMember(Member member) {
		this.member = member;
	}

	public UserDetailsImpl(Member member) {
		this.member = member;
	}

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {

		Collection<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
    Member m = memberRepository.findOne(getMember().getId());
//    Member m = memberRepository.findOne(this.getId());
//    Set<Role> roles = m.getRoles();

		authorities.add(new SimpleGrantedAuthority("ADMIN"));

		return authorities;

	}

  public Long getId() { return member.getId(); }

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

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

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

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

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

	@Override
	public boolean isEnabled() {
    return member.getEnabled();
	}
}


0

i tak też próbowałem bo z tego wszystkiego wydaję się najrozsądniejsze

 Set<Role> role = getMember().getRoles();

i dostaję Unable to evaluate the expression Method threw 'org.hibernate.LazyInitializationException' exception.

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