gpt4 book ai didi

java - Spring Boot 开启 @GlobalMethodSecurity 时出现异常

转载 作者:行者123 更新时间:2023-12-01 17:47:04 33 4
gpt4 key购买 nike

我正在尝试在 Spring Boot 中启用 @GlobalMethodSecurity 以使用 CustomPermissionEvaluator。因此,我添加了相应的 MethodSecurityExpressionHandler bean 并实现 CustomPermissionEvaluator。请参阅下面的来源。

问题。当我尝试在 WebSecurityConfigurerAdapter 中添加 @EnableGlobalMethodSecurity 时,出现以下错误:

Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'resourceHandlerMapping' threw exception; nested exception is java.lang.IllegalStateException: No ServletContext set*.

我搜索了解决方法,并找到了将 MethodSecurityExpressionHandler 移动到另一个 @Configuration 类中的建议。但这是正确的决定吗?我认为这是一个错误,已于 2016 年成功修复。 Github link

来源

WebSecurityConfigurerAdapter

@Configuration
@EnableWebSecurity //Turns on Spring's web security component
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
UserService userService;
@Autowired
UserDetailsServiceImpl userDetailsService;
@Autowired
private DataSource dataSource;
@Autowired
private CustomPermissionEvaluator permissionEvaluator;

@Bean
public BCryptPasswordEncoder passwordEncoder() {
//Password encoder settings to avoid storing plain passwords in DB
return new BCryptPasswordEncoder();
}

@Bean
public PersistentTokenRepository persistentTokenRepository() {
//Choose where to save user session: DB or memory (in our case: DB)
JdbcTokenRepositoryImpl db = new JdbcTokenRepositoryImplCust();
db.setDataSource(dataSource);
return db;
}

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
//Settings service to find User in DB + password
auth
.userDetailsService(userDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}

/* !Using method security here */
@Bean
public MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
handler.setPermissionEvaluator(permissionEvaluator);
return handler;
}

@Override
protected void configure(HttpSecurity http) throws Exception {
//Main method for Spring's web security
http
// URL checks
.authorizeRequests()
.antMatchers("/resource/**").permitAll() //All users can see it
.antMatchers("/users/**","/roles/**").hasAuthority("ADMIN") //Only users with Admin Role can see it
.anyRequest().authenticated() //All another URL requires authorization
.and()
// Login forms
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/main")//Redirect page if
.failureUrl("/login?error")
.usernameParameter("username") //parse from POST
.passwordParameter("password") //parse from POST
.permitAll()
.and()
// Actions when logoff
.logout()
.permitAll()
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout")
.invalidateHttpSession(true)
.and()
// Exceptions
.exceptionHandling()
.accessDeniedPage("/denied")
.and()
//Cookies
.rememberMe()
.tokenRepository(this.persistentTokenRepository()) //Choose sessions repository
.rememberMeParameter("remember-me")
.tokenValiditySeconds(1 * 24 * 60 * 60) //24H
;
}
}

权限评估器类

@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {
@Override
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
System.out.println("Permission eveluator: called");
boolean permissionGranted = false;
if (authentication != null && targetDomainObject instanceof String) {
//Checking if user have such role by evaluating Role object
Collection<Role> roles = (Collection<Role>) authentication.getAuthorities();
System.out.println("Permission eveluator: checking rights for: " + authentication.getPrincipal());

for (Role role : roles) {
if (role.getName().equals(targetDomainObject) && role.getPermission().getName() == permission) {
permissionGranted = true;
System.out.println("Permission eveluator: permission granted");
}
}
}
return permissionGranted;
}

@Override
public boolean hasPermission(Authentication authentication, Serializable serializable, String targetType,
Object permission) {
return false;
}
}

错误堆栈

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2020-03-25 16:18:45.206 ERROR 14044 --- [ main] o.s.boot.SpringApplication : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'resourceHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/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 'resourceHandlerMapping' threw exception; nested exception is java.lang.IllegalStateException: No ServletContext set
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:627) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:456) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1305) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1144) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:849) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142) ~[spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) [spring-boot-2.1.3.RELEASE.jar:2.1.3.RELEASE]
at com.platform.Application.main(Application.java:24) [classes/:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'resourceHandlerMapping' threw exception; nested exception is java.lang.IllegalStateException: No ServletContext set
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:622) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
... 19 common frames omitted
Caused by: java.lang.IllegalStateException: No ServletContext set
at org.springframework.util.Assert.state(Assert.java:73) ~[spring-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.resourceHandlerMapping(WebMvcConfigurationSupport.java:486) ~[spring-webmvc-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration$$EnhancerBySpringCGLIB$$ff99df16.CGLIB$resourceHandlerMapping$34(<generated>) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
at org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration$$EnhancerBySpringCGLIB$$ff99df16$$FastClassBySpringCGLIB$$eed8a8e5.invoke(<generated>) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363) ~[spring-context-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration$$EnhancerBySpringCGLIB$$ff99df16.resourceHandlerMapping(<generated>) ~[spring-boot-autoconfigure-2.1.3.RELEASE.jar:2.1.3.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_201]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_201]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_201]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
... 20 common frames omitted


Process finished with exit code 1

最佳答案

按照 Rob Winch 的建议,我将 @EnableGlobalMethodSecurity 移至单独的配置中,因此现在可以使用了。

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class CustomMethodSecurityConfig extends GlobalMethodSecurityConfiguration {

@Autowired
CustomPermissionEvaluator permissionEvaluator;

@Bean
public MethodSecurityExpressionHandler methodSecurityExpressionHandler() {
DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
handler.setPermissionEvaluator(permissionEvaluator);
return handler;
}

}

关于java - Spring Boot 开启 @GlobalMethodSecurity 时出现异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60851042/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com