请求使用@RolesAllowed保护的REST端点时,集成测试(生产代码运行良好)失败。 引发以下错误:
[5/20/19 8:44:21:363 CEST] 00000109 com.ibm.ws.security.jaspi.JaspiServiceImpl I CWWKS1652A: Authentication failed with status AuthStatus.SEND_FAILUR for the web request
/banking/users/bed6109f-ef8a-47ec-8fa4-e57c71415a10. The user defined Java Authentication SPI for Containers (JASPIC) service null has determined that the authentication data is not valid.
项目基于OpenLiberty with JWT。区别在于UI部分。我的UI基于Angular,因此为了进行身份验证(JWT发行),使用了REST Endpoint:
@RequestScoped
@Path("/tokens")
@PermitAll
public class AuthResource {
@Inject
private SecurityContext securityContext;
@Inject
private AuthService authService;
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getJwt() {
if (securityContext.isCallerInRole("USER") || securityContext.isCallerInRole("ADMIN")) {
String name = securityContext.getCallerPrincipal().getName();
AuthPojo authPojo = authService.createJwt(name);
return Response.ok(authPojo).build();
}
return Response.status(Response.Status.UNAUTHORIZED).build();
}
}
所以:
https://localhost:5051/tokens
调用"Authorization: Basic ENCODED_USERNAME_PASSWORD"
"Set-Cookie: LtpaToken2=SOME_TOKEN; Path=/; HttpOnly"
中以新生成的JWT令牌进行响应"@RolesAllowed({"ADMIN", "USER" })"
注释的REST端点的所有其他请求使用此令牌。再一次,在生产代码中,所有这些架构都可以正常工作,但是集成测试失败。
这是集成测试代码:
public class MyResourceIT {
private static final String URL = "https://localhost:" +
System.getProperty("liberty.test.ssl.port") + "/users/" + USER_ID1;
private String authHeader;
@Before
public void setup() throws Exception {
authHeader = "Bearer " + new JwtVerifier().createAdminJwt(USER_NAME1);
}
@Test
public void getUserAndAccounts() {
Response response = HttpClientHelper.processRequest(URL, "GET", null, authHeader);
System.out.println("My URL: " + URL);
System.out.println("My Header: " + authHeader);
assertThat("HTTP GET failed", response.getStatus(), is(Response.Status.OK.getStatusCode()));
}
}
看起来像为什么返回401而不是200的问题是LtpaToken2 Cookie,它在Test中没有设置。而是使用标题"Authorization: Bearer JWT_TOKEN"
,但这不起作用。
我希望提供头文件"@RolesAllowed"
时,受"Authorization: Bearer JWT_TOKEN"
保护的端点应以200响应。使用cookie应该有一些技巧吗?
更新2019-05-23
这是整个project。 测试示例位于here。测试失败被忽略
@Test
public void getUserAndAccounts_withJwt_authorized() throws IOException {
Response response = HttpClientHelper.processRequest(URL, "GET", null, authHeader, null);
assertThat(response.getStatus(), is(Response.Status.OK.getStatusCode()));
}
JWT令牌是在@Before注释方法的后class中创建的:
private String authHeader;
@Before
public void setup() throws Exception {
authHeader = "Bearer " + new JwtVerifier().createAdminJwt(USER_NAME1);
}
值得注意的是,该项目基于以下project。
答案 0 :(得分:0)
由于发出的CWWKS1652A消息没有提供程序名称,因此这表明已设置appSecurity-3.0,并且已通过注释或bean为该应用程序至少配置了JSR-375(又名Java EE安全API规范)HttpAuthenticationMechanism。实施。这将导致创建一个内部JASPIC提供程序,因此,在CWWKS1652A消息中为null,并且此提供程序调用已配置的HttpAuthenticationMechanism,该方法返回AuthStatus.SEND_FAILURE状态。
请确保您打算使用HttpAuthenticationMechanism,并在受到此机制的挑战时传递有效的身份验证凭据。
如果确定未配置HttpAuthenticationMechanism,则确定是否通过authconfigprovider.factory属性设置了外部JASPIC提供程序工厂(AuthConfigFactory实现)。无论哪种情况,都是提供者响应消息中显示的AuthStatus.SEND_FAILURE。