Spring Security的sec:authorize表达式失效问题求助
我需要为匿名用户显示登录标签,为拥有ROLE_USER权限的已认证用户显示登出标签,但使用sec:authorize表达式完全没有效果,也未抛出任何错误。以下是相关配置信息:
1. pom依赖配置
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.32</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webflux</artifactId> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.10.1</version> </dependency> <dependency> <groupId>io.projectreactor.netty</groupId> <artifactId>reactor-netty-http</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-taglibs</artifactId> </dependency> <dependency> <groupId>org.springframework.ldap</groupId> <artifactId>spring-ldap-core</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-ldap</artifactId> </dependency> <dependency> <groupId>com.unboundid</groupId> <artifactId>unboundid-ldapsdk</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
2. 匿名用户与已认证用户的Principal信息
匿名用户:
AnonymousAuthenticationToken [Principal=anonymousUser, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=null], Granted Authorities=[ROLE_ANONYMOUS]]
已认证用户:
UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=Balza, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[ROLE_USER]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=A2C735A0D12E494E89DC72BB9BAD7119], Granted Authorities=[ROLE_USER]]
3. Thymeleaf页面命名空间及sec:authorize代码
页面命名空间:
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5" lang="it">
按钮代码:
<li sec:authorize="hasRole('ROLE_ANONYMOUS')"><a class="dropdown-item" href="login">Login</a></li> <li sec:authorize="hasRole('ROLE_USER')"><a class="dropdown-item" href="perform_logout">Logout</a></li>
4. Security配置类代码
@Override protected void configure (final HttpSecurity http) throws Exception{ http .authorizeRequests() .antMatchers("/anonymus*").anonymous() //role anonymus .antMatchers("/login*").permitAll() .antMatchers("/static/**").permitAll() //resources .antMatchers("/addAuthors").hasRole("USER") .antMatchers("/*").permitAll() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .loginProcessingUrl("/perform_login") .failureUrl("/login?error=true") .permitAll() .defaultSuccessUrl("/", true) .and() .rememberMe() .key("superSecretKey") .tokenValiditySeconds(18000) //5 ore .tokenRepository(tokenRepository()) .and() .logout() .logoutSuccessUrl("/") .logoutRequestMatcher(new AntPathRequestMatcher("/perform_logout", "GET")) .invalidateHttpSession(true) .deleteCookies("JSESSIONID") .permitAll(); }
我尝试过使用<sec:authorize access="hasAnyAuthority('ANONYMOUS')">,但出现“Unknown html tag sec:authorize thymeleaf”错误;尝试获取登录用户名也无效,仿佛无法获取访问用户的信息。目前使用临时方案:
<li><a th:if="${role == '[ROLE_ANONYMOUS]'}" class="dropdown-item" href="login">Login</a></li> <li><a th:if="${role == '[ROLE_USER]'}" class="dropdown-item" href="perform_logout">Logout</a></li>
但不确定该方案是否正确,寻求正确的解决方法。
正确解决步骤
1. 修正sec:authorize表达式写法
- 匿名用户判断不要用
hasRole('ROLE_ANONYMOUS'),Spring Security提供了专门的isAnonymous()表达式,直接判断用户是否为匿名:<li sec:authorize="isAnonymous()"><a class="dropdown-item" href="login">Login</a></li> - 已认证用户的
ROLE_USER判断,hasRole('USER')即可,因为hasRole会自动拼接ROLE_前缀,与用户实际权限ROLE_USER匹配:<li sec:authorize="hasRole('USER')"><a class="dropdown-item" href="perform_logout">Logout</a></li>
2. 确保Thymeleaf集成Spring Security的方言被注册
如果Spring Boot自动配置未生效,手动添加配置类注册SpringSecurityDialect,让Thymeleaf能解析sec标签:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect; @Configuration public class ThymeleafConfig { @Bean public SpringSecurityDialect springSecurityDialect() { return new SpringSecurityDialect(); } }
3. 排查环境冲突问题
你依赖中同时包含了spring-webflux和Servlet相关依赖,确保项目是基于Spring MVC(Servlet)环境运行,WebFlux和Servlet混合可能导致Security上下文无法正确传递,影响sec标签解析。
4. 替换临时方案
你当前的临时方案依赖手动将权限放入Model,虽然能工作,但不够优雅且易出错,建议替换为上述标准的sec表达式写法。
内容的提问来源于stack exchange,提问作者Niccolò Balzarotti
相关产品推荐
相关产品推荐

