2015-07-30 4 views
0

Я реализовал свой собственный User и UserDetailsService из Spring Security, поскольку мне нужно сохранить дополнительную информацию в пользовательском объекте Spring Security. Однако я не думаю, что роли устанавливаются правильно. В базе данных и приложении пользователь может иметь 0,1 или несколько ролей.Роли безопасности безопасности не установлены должным образом

У меня есть следующий блок, на мой взгляд thymeleaf

<!-- header/navigation based on role of the user--> 
    <th:block sec:authorize="hasRole('ROLE_ADMIN')"> 
     <header th:include="fragments/header :: headerAdmin"></header> 
    </th:block> 
    <th:block sec:authorize="hasRole('ROLE_USER')"> 
     <header th:include="fragments/header :: headerUser"></header> 
    </th:block> 
    <th:block sec:authorize="isAnonymous()"> 
     <header th:include="fragments/header :: headerPublic"></header> 
    </th:block> 

Как только я не войти в систему ни один из этих шоу, но у меня есть ROLE_ADMIN по крайней мере, в базе данных.

Вот моя реализация UserDetailsService

@Service 
public class CustomUserDetailsService implements UserDetailsService { 

    private static final Logger logger = LoggerFactory.getLogger(CustomUserDetailsService.class); 

    @Autowired 
    private UserMapper userMapper; 

    @Override 
    public CustomUser loadUserByUsername(String email) throws UsernameNotFoundException { 

     logger.info("Authenticating user with email {}", email); 
     User user = userMapper.getUserByEmail(email); 
     if (user == null) { 
      throw new UsernameNotFoundException(String.format("User with email %s was not found", email)); 
     } 
     return new CustomUser(user); 
    } 
} 

И моя реализация Пользователь

public class CustomUser extends org.springframework.security.core.userdetails.User { 

    private User user; 

    public CustomUser(User user) { 
     super(user.getEmail(),user.getPassword(), AuthorityUtils.createAuthorityList(user.getRoles().toString())); 
     this.user = user; 
    } 

    public User getUser() { 
     return user; 
    } 

    public void setUser(User user) { 
     this.user = user; 
    } 

    public Collection<String> getRoles() { 
     return this.user.getRoles(); 
    } 

    @Override 
    public String toString() { 
     return MoreObjects.toStringHelper(this) 
       .add("user", user) 
       .toString(); 
    } 
} 

Я добавил этот блок в мой контроллер

@Controller 
public class HomeController { 

    private static Logger logger = LoggerFactory.getLogger(HomeController.class); 

    @RequestMapping(value = "/", method = RequestMethod.GET) 
    public String getHome() { 
     Collection<SimpleGrantedAuthority> authorities = (Collection<SimpleGrantedAuthority>) SecurityContextHolder.getContext().getAuthentication().getAuthorities(); 
     logger.info(authorities.toString()); 
     return "home/index"; 
    } 
} 

Оно напечатано следующее:

16:30:04.920 INFO HomeController.getHome - [[ROLE_ADMIN]] 

Для справки это объект домена пользователя MyBatis заполняемых

public class User implements Serializable { 

    private long id; 
    private String email; 
    private String password; 
    private String firstName; 
    private String lastName; 
    private long institutionId; 
    private char locked; 
    private Date createdAt; 
    private Date lastLogin; 
    private int failedLoginAttempts; 
    private Collection<String> roles; 

    public User() { 
    } 

    public long getId() { 
     return id; 
    } 

    public void setId(long id) { 
     this.id = id; 
    } 

    public String getEmail() { 
     return email; 
    } 

    public void setEmail(String email) { 
     this.email = email; 
    } 

    public String getPassword() { 
     return password; 
    } 

    public void setPassword(String password) { 
     this.password = password; 
    } 

    public String getFirstName() { 
     return firstName; 
    } 

    public void setFirstName(String firstName) { 
     this.firstName = firstName; 
    } 

    public String getLastName() { 
     return lastName; 
    } 

    public void setLastName(String lastName) { 
     this.lastName = lastName; 
    } 

    public long getInstitutionId() { 
     return institutionId; 
    } 

    public void setInstitutionId(long institutionId) { 
     this.institutionId = institutionId; 
    } 

    public char getLocked() { 
     return locked; 
    } 

    public void setLocked(char locked) { 
     this.locked = locked; 
    } 

    public Collection<String> getRoles() { 
     return roles; 
    } 

    public void setRoles(Collection<String> roles) { 
     this.roles = roles; 
    } 

    public Date getCreatedAt() { 
     return createdAt; 
    } 

    public void setCreatedAt(Date createdAt) { 
     this.createdAt = createdAt; 
    } 

    public Date getLastLogin() { 
     return lastLogin; 
    } 

    public void setLastLogin(Date lastLogin) { 
     this.lastLogin = lastLogin; 
    } 

    public int getFailedLoginAttempts() { 
     return failedLoginAttempts; 
    } 

    public void setFailedLoginAttempts(int failedLoginAttempts) { 
     this.failedLoginAttempts = failedLoginAttempts; 
    } 
} 

И в MyBatis Mapper

<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE mapper 
     PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
     "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 

<mapper namespace="org.ohtech.innovationexchange.persistence.UserMapper"> 

    <resultMap id="userMap" type="org.ohtech.innovationexchange.domain.User"> 
     <id column="ID" property="id" /> 
     <id column="EMAIL" property="email" /> 
     <id column="PASSWORD" property="password" /> 
     <id column="FIRST_NAME" property="firstName" /> 
     <id column="LAST_NAME" property="lastName" /> 
     <id column="INSTITUTION_ID" property="institutionId" /> 
     <id column="LOCKED" property="locked" /> 
     <id column="CREATED_AT" property="createdAt" /> 
     <id column="LAST_LOGIN" property="lastLogin" /> 
     <id column="FAILED_LOGIN_ATTEMPTS" property="failedLoginAttempts" /> 
     <collection property="roles" ofType="String"> 
      <id column="SPRING_NAME" /> 
     </collection> 
    </resultMap> 

    <select id="getUserByEmail" statementType="PREPARED" parameterType="String" resultMap="userMap"> 
     SELECT 
      u.ID, 
      u.EMAIL, 
      u.PASSWORD, 
      u.FIRST_NAME, 
      u.LAST_NAME, 
      u.INSTITUTION_ID, 
      u.LOCKED, 
      u.CREATED_AT, 
      u.LAST_LOGIN, 
      u.FAILED_LOGIN_ATTEMPTS, 
      r.SPRING_NAME 
     FROM T_USER u 
     INNER JOIN T_USER_ROLE tr 
      ON u.ID = tr.USER_ID 
     INNER JOIN T_ROLE r 
      ON tr.ROLE_ID = r.ID 
     WHERE EMAIL = #{email} 
    </select> 
</mapper> 

UPDATE:

Я обновил свой CustomUserDetailsService на следующее:

@Service 
public class CustomUserDetailsService implements UserDetailsService { 

    private static final Logger logger = LoggerFactory.getLogger(CustomUserDetailsService.class); 

    @Autowired 
    private UserMapper userMapper; 

    @Override 
    public CustomUser loadUserByUsername(String email) throws UsernameNotFoundException { 

     logger.info("Authenticating user with email {}", email); 
     User user = userMapper.getUserByEmail(email); 
     if (user == null) { 
      throw new UsernameNotFoundException(String.format("User with email %s was not found", email)); 
     } 

     Collection<GrantedAuthority> authorities = new HashSet<>(); 
     for (String role : user.getRoles()) { 
      authorities.add(new SimpleGrantedAuthority(role)); 
     } 

     return new CustomUser(user, authorities); 
    } 
} 

И CustomUser к:

public class CustomUser extends org.springframework.security.core.userdetails.User { 

    private User user; 

    public CustomUser(User user, Collection<GrantedAuthority> grantedAuthorities) { 
     super(user.getEmail(),user.getPassword(), grantedAuthorities); 
     this.user = user; 
    } 

    public User getUser() { 
     return user; 
    } 

    public void setUser(User user) { 
     this.user = user; 
    } 

    public Collection<String> getRoles() { 
     return this.user.getRoles(); 
    } 

    @Override 
    public String toString() { 
     return MoreObjects.toStringHelper(this) 
       .add("user", user) 
       .toString(); 
    } 
} 

Теперь печать:

18:02:29.045 INFO HomeController.getHome - [ROLE_ADMIN, ROLE_INSTITUTION_USER] 

Но мои блоки Thymeleaf сек до сих пор не работает.

ответ

1

Это неправильно:

AuthorityUtils.createAuthorityList(user.getRoles().toString()) 

Поскольку createAuthorityList не будет разбирать строковое представление коллекции. Вместо этого вы должны использовать что-то вроде:

AuthorityUtils.createAuthorityList(user.getRoles().toArray(new String[0])) 
+0

См. Мое обновление, я чувствую, что все еще могу делать что-то неправильно. Теперь это печать 18: 02: 29.045 INFO HomeController.getHome - [ROLE_ADMIN, ROLE_INSTITUTION_USER]. Я присвоил себе вторую роль вручную в базе данных. – greyfox

+0

Хорошо, это работает так, как сейчас. Спасибо, что указал мне в правильном направлении. – greyfox