当前位置: 首页 > 知识库问答 >
问题:

带Spring Security的Thymeleaf授权不工作[重复]

双浩涆
2023-03-14

我在我的Spring Boot应用程序中使用Spring Security,似乎Thymeleaf授权无法正常工作。

我有一个带有以下代码的Thymeleaf模板:

<div class="container">
    <div class="row" sec:authorize="isAuthenticated()">
        <h2 style="color:green">User is Logged In</h2>
        <p sec:authentication="principal.username">username</p>
    </div>

    <div class="row" sec:authorize="!isAuthenticated()">
        <h2 style="color:red">User is Logged Out</h2>
    </div>

    <div class="row" sec:authorize="hasRole('ROLE_SUPERUSER')">
        <h2>This will only be displayed if authenticated user has role ROLE_SUPERUSER.</h2>
    </div>

    <div class="row" sec:authorize="hasRole('ROLE_ADMIN')">
        <h2>This will only be displayed if authenticated user has role ROLE_ADMIN.</h2>
    </div>

    <div class="row" sec:authorize="hasRole('ROLE_USER')">
        <h2>This will only be displayed if authenticated user has role ROLE_USER.</h2>
    </div>

    <div th:if="${#authorization.expression('hasRole(''ROLE_ADMIN'')')}">
        This will only be displayed if authenticated user has role ROLE_ADMIN.
    </div>

    <div th:if="${#authorization.expr('hasRole(''ROLE_ADMIN'')')}">
        This will only be displayed if authenticated user has role ROLE_ADMIN.
    </div>
</div>

举例如下:https://github.com/thymeleaf/thymeleaf-extras-springsecurity

但是,显示的唯一内容是sec:authorize=“isAuthenticated()”sec:authorize=“!isAuthenticated()”,并且无论用户的角色如何,授权始终被忽略。

我的胸腺配置是:

@Configuration
public class ThymeleafConfig {

    @Bean
    public TemplateResolver defaultTemplateResolver() {
        TemplateResolver resolver = new TemplateResolver();
        resolver.setResourceResolver(thymeleafResourceResolver());
        resolver.setPrefix("classpath:/templates/");
        resolver.setSuffix(".html");
        resolver.setTemplateMode("HTML5");
        resolver.setCharacterEncoding("UTF-8");
        resolver.setCacheable(true);
        return resolver;
    }

    @Bean
    public SpringResourceResourceResolver thymeleafResourceResolver() {
        return new SpringResourceResourceResolver();
    }

    @Bean
    public SpringTemplateEngine templateEngine(TemplateResolver templateResolver) {
        SpringTemplateEngine engine = new SpringTemplateEngine();
        engine.setTemplateResolver(templateResolver);
        engine.addDialect(new SpringSecurityDialect());
        engine.addDialect(new LayoutDialect());
        return engine;
    }

    @Bean
    public ThymeleafViewResolver thymeleafViewResolver(SpringTemplateEngine templateEngine) {
        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setTemplateEngine(templateEngine);
        resolver.setCharacterEncoding("UTF-8");
        resolver.setContentType("text/html");
        resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 5);
        return resolver;
    }

}

我对thymeleaf-extras-springsecurity4使用以下依赖项:

<dependency>
    <groupId>org.thymeleaf.extras</groupId>
    <artifactId>thymeleaf-extras-springsecurity4</artifactId>
    <version>2.1.3.RELEASE</version>
</dependency>

版本<代码>3.0.2。RELEASE根本不起作用,sec命名空间总是被Thymeleaf忽略
我的Spring Boot版本是1.5.2。发布

原因可能是什么?

使现代化SecurityConfig中的configure(HttpSecurity http)方法如下所示:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf().ignoringAntMatchers("/h2-console").disable()
            .authorizeRequests()
                .antMatchers("/webjars/**", "/static/**", "/images/**", "/**/favicon.ico").permitAll()
                .antMatchers("/heat/**", "/power/**", "/water/**").permitAll()

            // start allowing h2-console
                .antMatchers("/h2-console/**").permitAll();
            http.csrf().disable();
            http.headers().frameOptions().disable()
            // end allowing h2-console

            .and().authorizeRequests().antMatchers("/info").permitAll()
            .and().authorizeRequests().antMatchers("/users/**").authenticated()
            .and().authorizeRequests().antMatchers("/users/**").hasAnyAuthority("ADMIN", "SUPERUSER")

            .and().formLogin()
                    .loginPage("/login")
                    .permitAll()
            .and()
                    .logout()
                    .permitAll()
                    .deleteCookies("remove")
                    .logoutUrl("/logout")
                    .logoutSuccessUrl("/")
                    .invalidateHttpSession(true)

            .and().exceptionHandling().accessDeniedPage("/access_denied");
}

来自IndexController的映射非常简单,它只返回登录模板:

@RequestMapping("/login")
public String loginForm() {
    return "login";
}

共有3个答案

锺离宸
2023-03-14

要尝试的事情:

1)用@EnableWebMvc注释您的配置。

2) 将ROLE_ADMIN替换为justADMIN(以及其他相应的角色)。

3) 在控制器中,打印以下内容以查看当前角色:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

Set<String> roles = authentication.getAuthorities().stream()
     .map(r -> r.getAuthority()).collect(Collectors.toSet());

System.out.println(roles);

如果这对您不起作用,可以尝试HttpServletRequest中的getUserPrincipal()

除此之外:

我加入了我的MVC配置,以便您可以尝试最新的Thymeleaf和Spring Security版本。这里有一些额外的配置,所以你可以删除与你的项目无关的内容。

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configuration) {

        configuration.enable();
    }

    @Bean
    public ThymeleafViewResolver viewResolver() {

        ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setOrder(1);
        resolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
        resolver.setTemplateEngine(templateEngine());
        return resolver;
    }

    @Bean
    public TemplateEngine templateEngine() {

        Set<ITemplateResolver> templateResolvers = new LinkedHashSet<>(1);
        templateResolvers.add(webTemplateResolver());

        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolvers(templateResolvers);
        Set<IDialect> dialects = new LinkedHashSet<>(2);
        dialects.add(new SpringSecurityDialect());
        dialects.add(new Java8TimeDialect());
        templateEngine.setAdditionalDialects(dialects);
        return templateEngine;
    }

    @Bean
    public ITemplateResolver webTemplateResolver() {

        SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
        resolver.setPrefix("/WEB-INF/thymeleaf/");
        resolver.setTemplateMode(TemplateMode.HTML);
        resolver.setCharacterEncoding(StandardCharsets.UTF_8.name());
        resolver.setSuffix(".html");
        resolver.setCacheable(false);
        resolver.setOrder(2);
        return resolver;
    }

    @Bean
    public ViewResolver tilesViewResolver() {

        UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();
        viewResolver.setViewClass(TilesView.class);
        viewResolver.setOrder(0);
        return viewResolver;
    }

    @Bean
    public TilesConfigurer tilesConfigurer() {

        TilesConfigurer configurer = new TilesConfigurer();
        configurer.setDefinitions("/WEB-INF/**/views.xml");
        return configurer;
    }

    @Bean
    public LocalValidatorFactoryBean validator() {

        return new LocalValidatorFactoryBean();
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {

        registry.addViewController("/403");
        registry.addViewController("/404");
        registry.addViewController("/about");
        //edited for brevity
    }

    @Bean
    public ReloadableResourceBundleMessageSource messageSource() {

        ReloadableResourceBundleMessageSource source = new ReloadableResourceBundleMessageSource();
        source.setBasename("classpath:messages");
        source.setDefaultEncoding(StandardCharsets.UTF_8.name());
        return source;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(localeChangeInterceptor());
        registry.addInterceptor(themeChangeInterceptor());
        registry.addInterceptor(deviceResolverHandlerInterceptor());
        super.addInterceptors(registry);
    }

    @Bean
    public HandlerInterceptor localeChangeInterceptor() {

        LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
        interceptor.setParamName("lang");
        return interceptor;
    }

    @Bean
    public HandlerInterceptor themeChangeInterceptor() {

        ThemeChangeInterceptor interceptor = new ThemeChangeInterceptor();
        interceptor.setParamName("theme");
        return interceptor;
    }

    @Bean
    public ResourceBundleThemeSource themeSource() {

        ResourceBundleThemeSource themeSource = new ResourceBundleThemeSource();
        themeSource.setBasenamePrefix("theme-");
        return themeSource;
    }

    @Bean
    public PersistedThemeResolver themeResolver() {

        PersistedThemeResolver resolver = new PersistedThemeResolver();
        resolver.setDefaultThemeName("default");
        return resolver;
    }

    @Bean
    public HandlerInterceptor deviceResolverHandlerInterceptor() {

        return new DeviceResolverHandlerInterceptor();
    }

    @Bean
    public CookieLocaleResolver localeResolver() {

        CookieLocaleResolver resolver = new CookieLocaleResolver();
        resolver.setDefaultLocale(Locale.US);
        return resolver;
    }

    //removed custom bean declaration

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {

        argumentResolvers.add(new ServletWebArgumentResolverAdapter(new DeviceWebArgumentResolver()));
        super.addArgumentResolvers(argumentResolvers);
    }

    @Bean
    public Executor taskExecutor() {

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(100);
        executor.initialize();
        return executor;
    }
}

工作pom摘录:

    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf</artifactId>
        <version>3.0.2.RELEASE</version>
        <exclusions>
            <exclusion>
                <groupId>javassist</groupId>
                <artifactId>javassist</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf-spring4</artifactId>
        <version>3.0.2.RELEASE</version>
    </dependency>

    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity4</artifactId>
        <version>3.0.0.RELEASE</version>
    </dependency>
梁丘扬
2023-03-14

在多次尝试不同的配置后,我找到了一个解决方法。在这种情况下,sec:authorize=“hasAuthority('ADMIN')”属性起作用:

<div class="row" sec:authorize="hasRole('ROLE_ADMIN')">
    <div class="col-md-10 col-md-offset-2">
        <h2>User Has Role Admin</h2>
    </div>
</div>
<div class="row" sec:authorize="hasAuthority('ADMIN')">
    <div class="col-md-10 col-md-offset-2">
        <h2>User Has Authority Admin</h2>
    </div>
</div>

用户有权限管理员头呈现在页面上。

仍然不知道为什么sec:authorize=“hasRole('ROLE_ADMIN')”属性不起作用,正如thymeleaf extras springsecurityGitHub页面上的一个示例所示:https://github.com/thymeleaf/thymeleaf-extras-springsecurity#using-属性

希望这能帮助一些人,尽管问题仍然悬而未决。

丁慈
2023-03-14

解决此任务的另一种方法是使用此语法检查角色:

<div class="row" th:if="${#request.isUserInRole('SUPERUSER')}">
    <h2>This will only be displayed if authenticated user has role ROLE_SUPERUSER.</h2>
</div>

它不使用sec命名空间,实际上完全不需要thymeleaf-exatas-springsecurity4依赖项来使用它。

 类似资料:
  • 我正在尝试使用Spring Boot、Spring Security4、Thymeleaf,如果用户有角色“admin”或其他任何东西,html块应该会显示出来,但现在它总是显示在页面上。这是我的html 这里是我的pom.xml,我添加了thymeleaf-extras-springsecurity4。还尝试了thymeleaf-extras-springsecurity3 这是我的securi

  • 默认情况下,SEC:authorize-URL标记不适用于Spring boot security: 添加依赖项 我是不是漏掉了什么?这是预期的行为吗?我需要定义什么才能使authorize-url像使用XML配置安全性时那样工作? 此问题与SpringBootWebSecurityConfiguration中的基本身份验证及其自动配置有关: 在SampleMethodSecurityApplic

  • 我的配置在这里 和 错误消息是:org.thymeleaf.templateparser.text.TextParseException:评估SpringEL表达式的异常:"book.price"(模板:"[#th: each="book:${book}"] - [(${ book.price})][/]"......原因:org.springframework.expression.spel.S

  • 我正在使用带Spring security的Thymeleaf模板引擎。为了使用sec:authorize功能,我还使用了Thymeleaf-Spring Security集成模块,但由于某些原因,它不起作用。我没有收到任何错误,但是html div块中的所有代码都会被执行,无论用户扮演哪个角色。 例如,当我以员工身份登录时,我也会看到“去领导”和“去系统”按钮,但我不想让员工看到这些按钮。 这是

  • 我有以下Spring Security配置: 我想让每个人(包括经过身份验证的用户和未经身份验证的用户)都可以访问特定的页面(比如索引页面(“/”),但同时,能够根据用户是否经过身份验证以及其角色来管理应该在jsp中看到哪些部分。 我的jsp部分如下所示: 所有的认证机制都可以正常工作。问题是,即使我使用“管理员”角色登录,链接也永远不会显示。 我尝试调试我的userdetails服务实现,并验证

  • 我发现了许多类似的问题,但没有一个解决了我的问题。我的问题是可以访问的函数 下面是我的spring-security.xml代码。