我们有一个受ResourceServer
保护的应用程序,并且我们正在使用GlobalMethodSecurity
来限制客户端范围对API端点的访问。一切都按预期进行。
我现在正在尝试编写一些集成测试。在我的测试中,我手动创建一个有效的JWT,然后调用受限端点。如果我没有发送令牌,则会如预期的那样得到401
,但是当我发送缺少必需范围的令牌时,它不会被拒绝,但能够到达端点。
我想我缺少使@PreAuthorize
正常工作的一些配置或设置,但是我不确定到底缺少什么。
这是我的考试班:
@RunWith(SpringRunner.class)
@WebAppConfiguration
@SpringBootTest
public class UserIT extends BaseIntegrationTest {
@Autowired
private UserRepository userRepository;
@Autowired
private WebApplicationContext wac;
@Autowired
private FilterChainProxy springSecurityFilterChain;
private MockMvc mockMvc;
@Before
public void setup () {
this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(springSecurityFilterChain).build();
}
@Test
public void cannotGetUsersWithoutToken () throws Exception {
mockMvc
.perform(get("/user/protected/user"))
.andExpect(status().isUnauthorized());
}
@Test
public void cannotGetUsersWithoutCorrectScope () throws Exception {
String token = getToken(Collections.singletonList("MY_ROLE"), 2);
mockMvc
.perform(get("/user/protected/user").header("Authorization", "Bearer " + token))
.andExpect(status().isUnauthorized());
}
}
这是API方法:
@PreAuthorize("isAuthenticated() and #oauth2.hasScope('my-scope')")
@RequestMapping(value="/user", method = RequestMethod.GET)
public UserInfo getUser(){
long userId = getUserId();
return userService.retrieveUser(userId);
}
第一个测试通过,但第二个失败;返回200
而不是401
。
关于我所缺少的任何建议将不胜感激。我一直在关注这个https://www.baeldung.com/oauth-api-testing-with-spring-mvc。
答案 0 :(得分:2)
答案在这里How to get @WebMvcTest work with OAuth?
您只需要创建一个界面即可在所需范围内模拟PreAuthorize。
@Retention(RetentionPolicy.RUNTIME)
@WithSecurityContext(factory = WithMockOAuth2Client.WithMockOAuth2ClientSecurityContextFactory.class)
public @interface WithMockOAuth2Client {
String clientId() default "web-client";
String[] scope() default {"openid"};
String[] authorities() default {};
boolean approved() default true;
class WithMockOAuth2ClientSecurityContextFactory implements WithSecurityContextFactory<WithMockOAuth2Client> {
public static OAuth2Request getOAuth2Request(final WithMockOAuth2Client annotation) {
final Set<? extends GrantedAuthority> authorities = Stream.of(annotation.authorities())
.map(auth -> new SimpleGrantedAuthority(auth))
.collect(Collectors.toSet());
final Set<String> scope = Stream.of(annotation.scope())
.collect(Collectors.toSet());
return new OAuth2Request(
null,
annotation.clientId(),
authorities,
annotation.approved(),
scope,
null,
null,
null,
null);
}
@Override
public SecurityContext createSecurityContext(final WithMockOAuth2Client annotation) {
final SecurityContext ctx = SecurityContextHolder.createEmptyContext();
ctx.setAuthentication(new OAuth2Authentication(getOAuth2Request(annotation), null));
SecurityContextHolder.setContext(ctx);
return ctx;
}
}
}
然后将它们用作测试
@Test
@WithMockOAuth2Client(scope={ "your-scope" })
...