Lorsque je me suis connecté avec la sécurité, je ne peux pas utiliser la méthode request.isUserInRole()
. Je pense que les rôles des utilisateurs n'étaient pas définis.
Voici ma configuration de sécurité:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled=true)
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
private UserDetailsServiceImplementation userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/signup").permitAll()
.antMatchers("/").permitAll()
//.antMatchers("/first").hasAuthority("Service_Center")
.antMatchers("/login").permitAll()
.anyRequest().fullyAuthenticated()
.and().formLogin()
.loginPage("/login")
.usernameParameter("email")
.passwordParameter("password")
.defaultSuccessUrl("/default")
.failureUrl("/login?error").permitAll()
.and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout")
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true).permitAll();
}
@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(userDetailsService);
}
}
Ceci est mon entité User
:
@Entity
@Table(name="user")
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="user_id")
private Long userID;
@Column(name="email_address", nullable = false, unique = true)
private String emailAddress;
@Column(name="password")
private String password;
@Column(name = "role", nullable = false)
@Enumerated(EnumType.STRING)
private Role role;
public User() {
super();
}
public User(String emailAddress, String password) {
this.emailAddress = emailAddress;
this.password = password;
}
public Long getUserID() {
return userID;
}
public void setUserID(Long userID) {
this.userID = userID;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
@Override
public String toString() {
return "User [userID=" + userID + ", emailAddress=" + emailAddress
+ ", password=" + password + ", role=" + role + "]";
}
public UserDetails toCurrentUserDetails() {
return CurrentUserDetails.create(this);
}
}
Ceci est mon enum Role
:
public enum Role {
Fleet_Company, Service_Center, Admin
}
C'est ma UserDetailsServiceImplementation
:
@Component
public class UserDetailsServiceImplementation implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
if ( username == null || username.isEmpty() ){
throw new UsernameNotFoundException("username is empty");
}
User foundUser = userRepository.findByEmailAddress(username);
if( foundUser != null ){
System.out.println("FOUND");
return foundUser.toCurrentUserDetails();
}
throw new UsernameNotFoundException( username + "is not found");
}
}
C'est la classe qui implémente UserDetails
:
public class CurrentUserDetails implements UserDetails {
private Long userID;
private String emailAddress;
private String password;
private Role role;
public CurrentUserDetails(Long userID, String emailAddress, String password, Role role) {
super();
this.userID = userID;
this.emailAddress = emailAddress;
this.password = password;
this.role = role;
}
/* public static UserDetails create(Users entity) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for(Authorities auth: entity.getAuthorities()){
authorities.add(new SimpleGrantedAuthority(auth.getId().getAuthority()));
}
return new MyUserDetail(entity.getUserId(), entity.getLoginId(), entity.getPassword(), entity.getDisplayName(), authorities);
}*/
public Long getUserID(){
return this.userID;
}
public Role getRole(){
return this.role;
}
@Override
public String getPassword() {
return this.password;
}
public String getEmailAddress() {
return this.emailAddress;
}
@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 static UserDetails create(User entity) {
System.out.println(entity.getUserID()+ entity.getEmailAddress()+ entity.getPassword()+ entity.getRole());
return new CurrentUserDetails(entity.getUserID(), entity.getEmailAddress(), entity.getPassword(), entity.getRole());
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getUsername() {
// TODO Auto-generated method stub
return null;
}
}
Donc, en gros, nous pouvons voir que je n’ai qu’une table dans ma base de données MySQL, elle a quatre colonnes et l’une d’elles est 'rôle'.
Mais comme ce que j'ai dit, lorsque j'utilise request.isUserInRole("Service_Center")
, il retourne FALSE. Et .antMatchers("/first").hasAuthority("Service_Center")
ne fonctionne pas non plus.
Vous devez renseigner vous-même le contenu du rôle lors de la création de vos détails utilisateur:
public class SecurityUser implements UserDetails{
String ROLE_PREFIX = "ROLE_";
String userName;
String password;
String role;
public SecurityUser(String username, String password, String role){
this.userName = username;
this.password = password;
this.role = role;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();
list.add(new SimpleGrantedAuthority(ROLE_PREFIX + role));
return list;
}
Fondamentalement, vous devez remplacer la méthode: getAuthorities
et remplir le contenu de votre champ de rôle dans la liste GrantedAuthority
.
Pour ajouter des rôles, vous devez disposer d'une table contenant le nom d'utilisateur et le rôle correspondant.
Supposons qu'un utilisateur ait deux rôles, à savoir ADMIN et USER.
Un utilisateur peut avoir plusieurs rôles.
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
final List<SimpleGrantedAuthority> authorities = new LinkedList<>();
if (enabled) {
if (this.getUser().isAdmin()) {
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
}
return authorities;
}
Cela peut s'appeler comme,
private UsernamePasswordAuthenticationToken getAuthentication(
final String token, final HttpServletRequest req,
final HttpServletResponse res){
return new UsernamePasswordAuthenticationToken(userAccount, null,
userAccount.getAuthorities());
}
Ce que Divelnto, Zapl et Thorinkor ont dit est juste. Mais la question devrait porter sur "Rôle" et NON "Rôles". OU, si vous avez des utilisateurs et des rôles dans une seule table, c'est une mauvaise conception. Vous voudrez peut-être revoir votre approche de conception. Vous devriez avoir une entité de rôle séparée. Et dans votre UserService, vous pouvez faire quelque chose comme:
AppUser user = userRepository.findByUsername(username);
Set<GrantedAuthority> grantedAuthorities = new HashSet<>(); // use list if you wish
for (AppRole role : user.getRoles()) {
grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
}
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
grantedAuthorities
);
Échantillons: échantillon1échantillon2échantillon3
Dans la base de données, vous pouvez stocker le nom du rôle sous la forme - (par exemple) ADMIN/EDITOR/VIEWER dans la base de données ou stocker les rôles sous la forme ROLE_ADMIN/ROLE _... alors vous pouvez utiliser hasRole/hasAuthoriy. J'espère que ça aide.
Pour référence, regardez ici: