Spring security oauth2 "no bean resolver registered" 錯誤踩坑
阿新 • • 發佈:2018-12-18
Spring security oauth2 “no bean resolver registered” 錯誤踩坑
錯誤堆疊資訊:
java.lang.IllegalArgumentException: Failed to evaluate expression '#oauth2.throwOnError(@rbacService.hasPermission(request, authentication))' Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1057E: No bean resolver registered in the context to resolve access to bean 'rbacService'
在實現rbac註解時,一開始參考他人程式碼,繼承的是WebSecurityConfigurerAdapter
,按如下程式碼執行後,發現帶上token訪問,獲得到的Authentication
為匿名使用者(其實是已經使用admin角色使用者登入。)。後參閱資料,猜測可能是注入順序的問題,加上@Order註解後,便修改了繼承類為ResourceServerConfigurerAdapter
,便出現上述錯誤堆疊資訊。
import com.jiandian.security.authentication.AuthorizeConfigManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; @EnableResourceServer @EnableWebSecurity @Configuration public class ApiSecurityConfig extends WebSecurityConfigurerAdapter { // Todo 這裡應該選擇哪個bean @Autowired private AuthorizeConfigManager coreAuthorizeConfigManagerImpl; @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/hello").permitAll(); // .anyRequest() // .access("@rbacService.hasPermission(request, authentication)"); coreAuthorizeConfigManagerImpl.config(http.authorizeRequests()); } }
在spring的github issue中,找到類似問題。
https://github.com/spring-projects/spring-security-oauth/issues/730#issuecomment-219480394
之後,加入了OAuth2WebSecurityExpressionHandler
,在ApiSecurityConfig
中加入程式碼,最後完整程式碼如下:
import com.jiandian.security.authentication.AuthorizeConfigManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler; @EnableResourceServer @EnableWebSecurity @Configuration public class ApiSecurityConfig extends ResourceServerConfigurerAdapter { // Todo 這裡應該選擇哪個bean @Autowired private AuthorizeConfigManager coreAuthorizeConfigManagerImpl; @Override public void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/hello").permitAll() .anyRequest() .access("@rbacService.hasPermission(request, authentication)"); } // 之後引入的bean是為了解決no bean resolver registered的問題 // https://github.com/spring-projects/spring-security-oauth/issues/730#issuecomment-219480394 @Autowired private OAuth2WebSecurityExpressionHandler expressionHandler; @Bean public OAuth2WebSecurityExpressionHandler oAuth2WebSecurityExpressionHandler(ApplicationContext applicationContext) { OAuth2WebSecurityExpressionHandler expressionHandler = new OAuth2WebSecurityExpressionHandler(); expressionHandler.setApplicationContext(applicationContext); return expressionHandler; } @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.expressionHandler(expressionHandler); } }