【发布时间】:2021-07-13 04:57:36
【问题描述】:
我正在尝试使用 sec:authentication="principal.authorities" 标签访问用户在 Thymeleaf 中的角色和权限,以便我可以控制向用户显示的内容。我的目标是检索“ROLE_ADMIN”或“ROLE_USER”,但它似乎是检索与该角色关联的三个权限,“[CHANGE_PASSWORD_PRIVILEGE, READ_PRIVILEGE, WRITE_PRIVILEGE]”。
我希望有人能帮助我进一步了解 Principal 对象和从 springframework 实现 UserDetails 的 User 类。我对权限属性以及如何从中检索用户的“角色”特别感兴趣。这是我第一次实现这一点,所以我相信我还有更多需要学习的东西。非常感谢任何帮助!
注意*这是我的第一篇文章,所以看来我的图片有限。我现在会尽力处理文字。
当前结果和实施
这是在我的 profile.html 页面上呈现的内容。
当前用户角色:[CHANGE_PASSWORD_PRIVILEGE, READ_PRIVILEGE, WRITE_PRIVILEGE]
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/web/thymeleaf/layout"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security" layout:decorator="layout">
<head>
<title>Profile</title>
</head>
<body>
<h1 layout:fragment="header">Profile</h1>
<div layout:fragment="content" class="container">
Current user name:
<span sec:authentication="principal.username">User</span>
<br/>
Current user name 2:
<span sec:authentication="name">User</span>
<br/>
<br/>
Current user roles:
<span sec:authentication="principal.authorities">[ROLE_USER, ROLE_ADMIN]</span>
<br/>
<div sec:authorize="hasRole('ROLE_ADMIN')">
Current user roles 2:
<span sec:authentication="authorities">[ROLE_USER, ROLE_ADMIN]</span>
</div>
</div>
</body>
</html>
@Service
@Transactional
public class MyUserDetailsService implements UserDetailsService {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired
private UserRepository userRepository;
@Autowired
private LoginAttemptService loginAttemptService;
@Autowired
private HttpServletRequest request;
public MyUserDetailsService() {
super();
}
@Override
public UserDetails loadUserByUsername(final String email) throws UsernameNotFoundException {
try {
final User user = userRepository.findByEmail(email);
if (user == null) {
throw new UsernameNotFoundException("No user found with username: " + email);
}
log.info("User: " + user.getEmail() + " Password: " + user.getPassword() + "Role: " + user.getRoles());
return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), true, true, true, true, getAuthorities(user.getRoles()));
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
private Collection<? extends GrantedAuthority> getAuthorities(Collection<Role> roles) {
return getGrantedAuthorities(getPrivileges(roles));
}
private List<String> getPrivileges(Collection<Role> roles) {
final List<String> privileges = new ArrayList<>();
final List<Privilege> collection = new ArrayList<>();
for (final Role role : roles) {
collection.addAll(role.getPrivileges());
}
for (final Privilege item : collection) {
privileges.add(item.getName());
}
return privileges;
}
private List<GrantedAuthority> getGrantedAuthorities(List<String> privileges) {
final List<GrantedAuthority> authorities = new ArrayList<>();
for (String privilege : privileges) {
authorities.add(new SimpleGrantedAuthority(privilege));
}
return authorities;
}
}
这是我从 loadUserByName 方法记录 user.getRole() 时显示的内容。 “[角色 [id=4, name=ROLE_ADMIN]]”
Maven
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
User.class
* @param authorities the authorities that should be granted to the caller if they
* presented the correct username and password and the user is enabled. Not null.
*
* @throws IllegalArgumentException if a <code>null</code> value was passed either as
* a parameter or as an element in the <code>GrantedAuthority</code> collection
*/
public User(String username, String password, boolean enabled,
boolean accountNonExpired, boolean credentialsNonExpired,
boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
if (((username == null) || "".equals(username)) || (password == null)) {
throw new IllegalArgumentException(
"Cannot pass null or empty values to constructor");
}
this.username = username;
this.password = password;
this.enabled = enabled;
this.accountNonExpired = accountNonExpired;
this.credentialsNonExpired = credentialsNonExpired;
this.accountNonLocked = accountNonLocked;
this.authorities = Collections.unmodifiableSet(sortAuthorities(authorities));
}
【问题讨论】:
-
为什么要从
Privile值创建SimpleGrantedAuthority?您是否尝试过改用Role值? -
我已将字符串“ROLE_ADMIN”作为硬编码值传递给
new SimpleGrantedAuthority("ROLE_ADMIN"),并且我的html 中的sec:authorize标记将按预期工作。我想我的假设是 User.class 中的authorities属性将包含Roles和Privileges的集合,并且principal.authorities将能够识别其中的Roles。但是,我想我意识到我实际上并没有将Roles存储在那里,只有Privileges被传递。
标签: java spring authentication thymeleaf roles