Thymeleaf sec:身份验证标签不显示角色

Posted

技术标签:

【中文标题】Thymeleaf sec:身份验证标签不显示角色【英文标题】:Thymeleaf sec:authentication tag not displaying role 【发布时间】: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>
这是 MyUserDetailsS​​ervice 实现 UserDetailsS​​ervice
@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 属性将包含 RolesPrivileges 的集合,并且 principal.authorities 将能够识别其中的 Roles。但是,我想我意识到我实际上并没有将Roles 存储在那里,只有Privileges 被传递。 【参考方案1】:

您将Privileges 传递给SimpleGrantedAuthority 构造函数,而您应该传递Roles

检查您传递给SimpleGrantedAuthority 的实际字符串值,这应该与您在&lt;div sec:authorize="hasRole('ADMIN')"&gt;&lt;div sec:authorize="hasAuthority('ROLE_ADMIN')"&gt; 中使用的匹配(如果您需要以ROLE_ 为前缀,则存在差异)

【讨论】:

维姆,谢谢您的回复!我确实为你的答案投票,但我是新手,所以在我的代表增加之前它不会计算在内。你肯定能解决我遇到的问题并提供一个好的解决方案。

以上是关于Thymeleaf sec:身份验证标签不显示角色的主要内容,如果未能解决你的问题,请参考以下文章

Thymeleaf 不解释 sec 标签

Thymeleaf spring 安全方言根本不起作用

Spring Boot Security - Thymeleaf sec:授权不起作用

Thymeleaf hasRole 在 JavaScript 中可见

thymeleaf中security的sec:authorize标签不起作用的原因

thymeleaf中security的sec:authorize标签不起作用的原因