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