我一直在关注本指南,了解如何使用 Keycloak 保护我的 JAX-RS API。我正在执行它提供的所有步骤,但遗憾的是我无法让我的身份验证正常工作。我的请求总是导致 401 响应。我希望你们中的一些人可以帮助我解决这个问题。
我使用 docker-compose 来运行所有容器。
docker-compose.yaml
version: '3'
services:
products:
image: maven:alpine
volumes:
- ./products/target/:/usr/src/products
command: java -jar /usr/src/products/products-0.0.1.jar
environment:
MYSQL_USER: mysql
MYSQL_PASS: mysql
ports:
- 8000:8080
networks:
- keycloak
keycloak:
image: jboss/keycloak
environment:
KEYCLOAK_USER: keycloak
KEYCLOAK_PASSWORD: keycloak
DB_VENDOR: postgres
DB_ADDR: keycloakDb
DB_USER: keycloak
DB_PASSWORD: password
ports:
- 8100:8080
depends_on:
- keycloakDb
networks:
- keycloak
keycloakDb:
image: postgres
volumes:
- ./volumes/keycloak/data:/var/lib/postgresql
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: password
networks:
- keycloak
networks:
keycloak:
driver: bridge
我使用这些设置来配置 Kumuluz
config.yaml
kumuluzee:
security:
keycloak:
json: '{
"realm": "producerstore-realm",
"bearer-only": true,
"auth-server-url": "http://keycloak:8080/auth",
"ssl-required": "external",
"resource": "producerstore-api",
"confidential-port": 0
}'
这是我的 JAX-RS 应用程序和 REST 资源。
Api.java
@ApplicationPath("")
@DeclareRoles({"admin", "customer"})
public class Api extends Application {
}
ProductResource.java
@GET
@PermitAll
@Path("/products")
public Response getAll() {
try {
return Response.ok()
.entity(service.getAll())
.build();
} catch (Exception e) {
return internalServerError(e.getMessage());
}
}
@POST
@RolesAllowed({"admin"})
@Path("/products")
public Response createProduct(ProductDto productDto, @Context UriInfo uriInfo) {
try {
long createdId = service.add(productDto);
URI uri = uriInfo.getAbsolutePathBuilder()
.segment(Long.toString(createdId))
.build();
return Response.created(uri)
.build();
} catch (CreationException e) {
return internalServerError(e.getMessage());
}
}
我还在 Keycloak 中定义了管理员和客户角色。接下来,我创建了一个用户并将这些角色分配给他们。
当我使用该用户登录时,我会收到正确的 JWT。
curl -X POST \
http://localhost:8100/auth/realms/producerstore-realm/protocol/openid-connect/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=password&client_id=producerstore-app&username=<username>&password=<password>'
这导致以下标记
{
"access_token": "<very-long-token>",
"expires_in": 300,
"refresh_expires_in": 1800,
"refresh_token": "<another-very-long-token>",
"token_type": "bearer",
"not-before-policy": 0,
"session_state": "770908df-08fa-4935-8666-a58ae41447e7",
"scope": "profile email"
}
但是当我尝试请求我的资源时,它总是会导致 401。
curl -X GET \
http://localhost:8000/products \
-H 'Authorization: Bearer <very-long-token>'
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Error 401 Unauthorized</title>
</head>
<body>
<h2>HTTP ERROR 401</h2>
<p>Problem accessing /products. Reason:
<pre> Unauthorized</pre>
</p>
<hr>
<a href="http://eclipse.org/jetty">Powered by Jetty:// 9.4.15.v20190215</a>
<hr/>
</body>
</html>
我希望你们中的一些人可以帮助我解决这个问题,如果您需要更多关于某些事情的信息,我会很乐意提供。
谢谢!