我正在创建自定义角色层次结构,并尝试将其与基于Web的安全性和方法级别安全性一起使用。这是一个Spring Boot Web应用程序。
我的配置文件:
@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled=true,prePostEnabled=true)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
SecurityConfig:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
ApplicationContext applicationContext;
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.formLogin()
.loginPage("/signin.html")
.loginProcessingUrl("/signin/authenticate")
.failureUrl("/signin?param.error=bad_credentials")
.and()
.logout()
.logoutUrl("/signout")
.deleteCookies("JSESSIONID")
.and()
.authorizeRequests()
.expressionHandler(webExpressionHandler())
.antMatchers("/signin**","/user/**","/admin/**", "/favicon.ico", "/resources/**", "/auth/**", "/signin/**", "/signup/**").permitAll()
.antMatchers("/doc/**").hasRole("MOD").anyRequest().authenticated()
.and()
.apply(springSocialConfigurer())
.and()
.rememberMe();
}
//Some more code for Spring Social integration
@Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_MOD > ROLE_USER > ROLE_GUEST");
return roleHierarchy;
}
private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() {
DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
defaultWebSecurityExpressionHandler.setApplicationContext(applicationContext);
defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy());
return defaultWebSecurityExpressionHandler;
}
@Bean
public RoleHierarchyVoter roleHierarchyVoter() {
return new RoleHierarchyVoter(roleHierarchy());
}
GlobalMethodSecurityConfig
@Configuration
public class GlobalMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Autowired
private RoleHierarchy roleHierarchy;
@Autowired
ApplicationContext applicationContext;
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
System.out.println("Method Security configured");
DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
expressionHandler.setApplicationContext(applicationContext);
expressionHandler.setRoleHierarchy(roleHierarchy);
return expressionHandler;
}
}
现在,我注意到方法createExpressionHandler()永远不会被调用。那可能是因为我在Application类中添加了注释@EnableGlobalMethodSecurity? 如果我将注释放在GlobalMethodSecurityConfig类上,那么该方法将被调用,但是当我运行该程序时,我得到一个异常,其中说:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultServletHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'defaultServletHandlerMapping' threw exception; nested exception is java.lang.IllegalArgumentException: A ServletContext is required to configure default servlet handling
我无法弄清楚我在这里做错了什么。请帮忙。
编辑1 -------------
好的,我想我有一些想法,发生了什么。需要尽早配置Spring Security过滤器。因此,将RoleHierarchy Bean的创建移动到单独的配置文件可能会解决问题。我刚刚这样做了,我能够成功编译和运行代码。我在其他Configuration类中有自动装配的RoleHierarchy。自定义角色ROLE_MOD也可以。但是,问题还没有解决。
由于ROLE_MOD高于层次结构中的ROLE_USER,因此具有ROLE_MOD的用户是否有资格访问有权访问ROLE_USER的方法?
@PreAuthorize("hasRole('ROLE_USER')")
这对于使用ROLE_MOD的用户不起作用,我得到一个AccessDeniedException。我想知道这是否是配置自定义角色层次结构的正确方法。请帮帮我。
编辑2 -------------
好的,我对定义自定义角色层次结构的方式做了一些改动。 我改成了:
roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_MOD and ROLE_MOD > ROLE_USER and ROLE_USER > ROLE_GUEST");
现在一切正常!谢谢你给我一个大声思考的空间!