Java 如何从当前用户获取角色?

Java 如何从当前用户获取角色?,java,kotlin,keycloak,vert.x,Java,Kotlin,Keycloak,Vert.x,我尝试使用JWT实现AuthN/AuthZ,如下所示: class MainVerticle : CoroutineVerticle() { private suspend fun initConfig(): JsonObject { val yamlConfigOpts = ConfigStoreOptions() .setFormat("yaml") .setType("file") .setConfi

我尝试使用JWT实现AuthN/AuthZ,如下所示:

class MainVerticle : CoroutineVerticle() {

  private suspend fun initConfig(): JsonObject {
    val yamlConfigOpts = ConfigStoreOptions()
      .setFormat("yaml")
      .setType("file")
      .setConfig(JsonObject().put("path", "config.yaml"))

    val configRetrieverOpts = ConfigRetrieverOptions()
      .addStore(yamlConfigOpts)

    val configRetriever = ConfigRetriever.create(vertx, configRetrieverOpts)

    return configRetriever.config.await()
  }


  private suspend fun createJwtAuth(client: WebClient, config: JsonObject): JWTAuth? {

    val issuer = config.getJsonObject("jwt").getString("issuer")

    // derive JWKS uri from Keycloak issuer URI
    val jwksUri = URI.create("${issuer}/protocol/openid-connect/certs")

    // The exception will be caught above
    val res = client.get(jwksUri.host, jwksUri.path).send().await()

    return res.bodyAsJsonObject()?.let {
      val keys = it.getJsonArray("keys")

      val jwtOpt = JWTOptions()
      jwtOpt.issuer = issuer


      // configure JWTAuth
      val jwtAuthOptions = JWTAuthOptions()

      jwtAuthOptions.jwks = (keys.list as List<Map<String, *>>)
        .map { json -> JsonObject(json) }
        .map { json -> json.put("permissionsClaimKey", "realm_access/roles") }
      jwtAuthOptions.jwtOptions = jwtOpt



      JWTAuth.create(vertx, jwtAuthOptions)
    } ?: throw AuthenticationException("Can not receive the token")

  }

  private fun createRoutes(router: Router, jwtAuth: JWTAuth): Unit {

    router.route("/api/*").handler(JWTAuthHandler.create(jwtAuth))

    router.route("/api/greet").handler {

      val token = it.request().getHeader(HttpHeaders.AUTHORIZATION).substring("Bearer ".length)

      jwtAuth.authenticate(JsonObject().put("jwt", token))
        .onSuccess { user ->
          val res = it.response()
          res.putHeader("content-type", "text/plain")

          // Write to the response and end it
          res.end("I am interests path")
        }
        .onFailure { err -> it.response().setStatusCode(403).end(err.message) }


    }

  }


  private suspend fun server(router: Router): HttpServer {
    val server = vertx.createHttpServer()

    return server.requestHandler(router)
      .listen(8080)
      .onSuccess {
        println("HTTP server started on port ${it.actualPort()}")
      }
      .onFailure {
        println("Failed to start the server. Reason ${it.message}")
      }
      .await()
  }


  override suspend fun start() {

    val config = initConfig()
    val webClient = WebClient.create(vertx)
    val router = Router.router(vertx)

    createJwtAuth(webClient, config)?.let {
      createRoutes(router, it)
      server(router)

    }
  }
}
线路

println(it.user().principal().getString("preferred_username"))

打印
null
而不是用户名。我做错了什么?

当您使用最新版本时,让我解释一下新API中的更改。在4.0.0中,我们将
authn
authz
分开,因此在您的示例中,您已经正确执行了
authn
,并获得了
User
对象实例

现在您想要提取权限,因为您正在执行
JWTAuth
您正在使用“低”级别的路径,而如果您要使用
OAuth2Auth
则不需要执行某些操作(例如加载密钥等)

既然有了用户对象,就需要有一个
authz
提取对象。为此,我将以java API为例,但在Kotlin中,它应该非常类似:

// First create a JWTAuthorization object
JWTAuthorization.create("realm_access/roles")
  .getAuthorizations(user)
  .onSuccess(success -> {
    // The authorizations have been successfully extracted from the user
    // Now you can perform any kind of checks

    if (PermissionBasedAuthorization.create("write").match(user)) {
      // ... User is allowed to write...
    }
  });
因此,权限是从传递给提取器的
claimKey
下的
属性中提取的。简而言之,
属性
是由框架生成的,或者是解码/验证的数据,而
主体
是为创建用户而提供的源数据。区别很重要,因为现在用户对象可以用于服务器验证和客户端请求


这也意味着保持源代码不被触动,解码不会覆盖重要数据(如过期日期等)的风险。

您是否尝试查看令牌中的内容?我的意思是,您是否复制了“access_token”的值并将其签入,以查看您是否需要角色或其他声明。已经存在并具有适当的值?在
访问\u令牌
中,我可以看到所有相关信息
领域访问
等。我是否正确理解您,我应该使用正确的方法?我想做的是,用KeyClope保护我的api服务。我很困惑。
// First create a JWTAuthorization object
JWTAuthorization.create("realm_access/roles")
  .getAuthorizations(user)
  .onSuccess(success -> {
    // The authorizations have been successfully extracted from the user
    // Now you can perform any kind of checks

    if (PermissionBasedAuthorization.create("write").match(user)) {
      // ... User is allowed to write...
    }
  });