首页 文章

使用Spring Security进行Thymeleaf授权不起作用[重复]

提问于
浏览
5

这个问题在这里已有答案:

我在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 根本不起作用,并且Thymeleaf总是忽略 sec 名称空间 .
我的Spring Boot版本是 1.5.2.RELEASE .

可能是什么原因?

UPDATE. 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 的映射非常简单,它只返回 login 模板:

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

3 回答

  • 7

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

    <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-extras-springsecurity4依赖 .

  • 1

    经过不同配置的大量尝试后,我找到了一种解决方法 . 在这种情况下 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>
    

    User Has Authority Admin 页面上的 Headers 呈现 .

    仍然不知道为什么 sec:authorize="hasRole('ROLE_ADMIN')" 属性不起作用,因为它建议在 thymeleaf-extras-springsecurity GitHub页面上作为示例:https://github.com/thymeleaf/thymeleaf-extras-springsecurity#using-the-attributes

    希望这可以帮助某人,尽管问题仍然存在 .

  • 1

    要尝试的事情:

    1)使用 @EnableWebMvc 注释您的配置 .

    2)将 ROLE_ADMIN 替换为 ADMIN (以及其他相应的) .

    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() .

    Short of that:

    我包含我的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>
    

相关问题