gpt4 book ai didi

java - Spring Boot 2 @WebMvcTest 和 OAuth2 #oauth2.hasScope Controller 导致 IllegalArgumentException

转载 作者:行者123 更新时间:2023-12-05 06:29:58 25 4
gpt4 key购买 nike

这是一个使用 MVC Controller 的 spring boot 2.0.6 应用程序,使用@PreAuthorize 和#oauth2.hasScope 来保护 Controller 端点。我已经使用 @WebMvcTest 编写了测试来编写 Controller 测试。似乎正在发出请求,但是当 #oauth2.hasScope 被调用时,它没有给出一个值来与某处进行比较。我有什么问题?

异常

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalArgumentException: Failed to evaluate expression '#oauth2.hasScope('foo')'

at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:866)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:71)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:166)
at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:133)
...
Caused by: java.lang.IllegalArgumentException: Failed to evaluate expression '#oauth2.hasScope('eq.distributor')'
at org.springframework.security.access.expression.ExpressionUtils.evaluateAsBoolean(ExpressionUtils.java:30)
at org.springframework.security.access.expression.method.ExpressionBasedPreInvocationAdvice.before(ExpressionBasedPreInvocationAdvice.java:59)
at org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter.vote(PreInvocationAuthorizationAdviceVoter.java:72)
... 72 more
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1011E: Method call: Attempted to call method hasScope(java.lang.String) on null context object
at org.springframework.expression.spel.ast.MethodReference.throwIfNotNullSafe(MethodReference.java:153)
at org.springframework.expression.spel.ast.MethodReference.getValueRef(MethodReference.java:82)
... 94 more

测试类

@RunWith(SpringRunner.class)
@WebMvcTest
public class MockMvcTestBase {
@Autowired
protected WebApplicationContext context;

private ObjectMapper objectMapper;

private MockMvc mockMvc;

@Before
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
.apply(documentationConfiguration(this.restDocumentation)
.uris()
.withScheme("http")
.withHost("development.com")
.withPort(80))
.alwaysDo(document("{method-name}", preprocessRequest(prettyPrint()), preprocessResponse(prettyPrint())))
.apply(springSecurity())
.build();

this.objectMapper = new ObjectMapper();
}


@Test
@WithMockUser(username = "testclient", authorities = "foo")
public void givenValidUser_whenGetOrderDetailsWebEC_thenGetOrder() throws Exception {
getMockMvc().perform(get("/ok")
.header("Authorization", authorizationHeader()))
.andExpect(status().isOk())
.andExpect(content().string("ok"));
}
}

授权配置

@Configuration
@EnableAuthorizationServer
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true)
@SuppressWarnings("static-method")
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

@Bean
public static PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}

@Override
public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("testclient")
.secret("password")
.authorizedGrantTypes("client_credentials")
.accessTokenValiditySeconds(0)
.scopes("foo")
.and()
.withClient("bar")
.secret("password")
.authorizedGrantTypes("client_credentials")
.accessTokenValiditySeconds(0)
.scopes("eq.distributor");
}
}

Controller

@PreAuthorize("#oauth2.hasScope('foo')")
@RequestMapping(value = "/ok", method = RequestMethod.GET)
public String ok() {
return "ok";
}

Spring Security 调试输出

org.springframework.mock.web.MockHttpServletRequest@54704b46

servletPath:
pathInfo:/ok
headers:
Authorization: Bearer 57962883-e379-433b-b613-1f888471fb84
Accept: application/json;charset=UTF-8


Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
LogoutFilter
OAuth2AuthenticationProcessingFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]

任何关于我在设置中遗漏的帮助都会非常有帮助。似乎确实有问题,就好像它实际上是在尝试进行身份验证一样,会返回 401/403。也不异常(exception)。减去进行此编译所需的更改,这在 Spring Boot 1.5.9 下有效。

如果我为 @SpringBootTest 换掉模拟 mvc 注释,这是可行的,但是我不需要这些测试的数据库,所以我想将其设置为不需要加载它。

最佳答案

发生这种情况是因为 Spring 使用了 DefaultMethodSecurityExpressionHandler。看到这个:#oauth2 security expressions on method level

要解决这个问题,请执行以下操作:

  1. AuthorizationServerConfig 中删除 @EnableGlobalMethodSecurity
  2. 添加以下新的配置类

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class MethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new OAuth2MethodSecurityExpressionHandler();
}
}

对我来说重要的是,我已经在另一个配置上添加了 @EnableGlobalMethodSecurity,所以 spring 最初忽略了新的配置类

关于java - Spring Boot 2 @WebMvcTest 和 OAuth2 #oauth2.hasScope Controller 导致 IllegalArgumentException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52881792/

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