繁体   English   中英

在Play(Java)中实现OAuth2的密码所有者资源流

[英]Implementing the password owner resource flow of OAuth2 in Play (Java)

对于我的学士论文,我必须使用不同的框架来实现不同种类的身份验证和授权。 目前,我在OAuth2一章中讲过,必须在Play框架(Java)中实现它。 (我已经使用Spring Boot实现了它)到目前为止,在研究如何解决此问题时,我找不到很多有用的技巧。

我的主要问题之一是:在客户端使用用户凭据对自身进行身份验证并获得令牌后,如何最好地验证令牌? 基本上:Spring的“ @PreAuthorize”注释的Play对应部分是什么?

任何提示或链接到有用的网站表示赞赏。

所以我想我解决了我的问题。 如果有人偶然发现相同的问题,我将在此处发布解决方案:

正如使用OAuth2(尤其是使用密码流)在Play文档( https://www.playframework.com/documentation/2.6.x/JavaOAuth )中编写的那样,它非常简单。

首先,您需要一个Authorization-Service,这里的实现很简单。 只需实现三种方法:

POST / oauth / token用于传递用户凭证并接收访问令牌和刷新令牌

当访问令牌不再有效时,POST / oauth / refresh。 这里传递了刷新令牌,并返回了新的acces令牌

POST / oauth / check_token进行授权。 这里传递了访问令牌,在我的情况下,我返回了用户的角​​色。 或者,也可以在授权服务中进行授权过程,甚至可能更好。 为此,您需要更改“ check_token”方法并传递所需的角色。

我只是将uuid生成为令牌,并将它们存储在数据库中。 我猜也可以使用例如jwts并将所需的信息(例如到期日期)放入令牌中。

然后我的主要问题是关于注释。 我找到了这个https://github.com/bekce/oauthly ,只是看一下它们的实现。

您基本上只需要一个类和一个接口:

接口:

@With(AuthorizationServerAuthAction.class)
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthorizationServerSecure {
    boolean requireAdmin() default false;
    boolean requirePersonnel() default false;
    boolean requireGuest() default false;
}

班级:

private WSClient ws;
private final String url = "http://localhost:9001/oauth/check_token";
@Inject
public AuthorizationServerAuthAction(WSClient ws) {
    this.ws = ws;
}

private CompletionStage<JsonNode> callApi(String accessToken) {
    CompletionStage<WSResponse> eventualResponse =  ws.url(url).setContentType("application/x-www-form-urlencoded").setRequestTimeout(Duration.ofSeconds(10))
            .addHeader("Authorization" ,  accessToken).post("none");
    return eventualResponse.thenApply(WSResponse::asJson);
}
@Override
public CompletionStage<Result> call(Http.Context ctx) {
    Optional<String> accessTokenOptional = ctx.request().header("Authorization");
    JsonNode result = null;
    if(!accessTokenOptional.isPresent()){
        return CompletableFuture.completedFuture(unauthorized(Json.newObject()
                .put("message", "No token found in header!")
        ));
    }

    CompletionStage<JsonNode> apiResponse = callApi(accessTokenOptional.get());
    try {
        result = apiResponse.toCompletableFuture().get();
    } catch (InterruptedException | ExecutionException e) {
        e.printStackTrace();
    }
    if(result == null) {
        return CompletableFuture.completedFuture(unauthorized(Json.newObject()
                .put("message", "an error occurred")
        ));
    }
    String role = result.get("role").asText();

    if(configuration.requireAdmin()){
        if(role.equals("admin")) {
            return delegate.call(ctx);
        } else {
            return CompletableFuture.completedFuture(unauthorized(Json.newObject()
                    .put("message", "The user is not authorized to perform this action!")
            ));
        }
    } else if(configuration.requirePersonnel()) {
        if(role.equals("personnel") || role.equals("admin")) {
            return delegate.call(ctx);
        } else {
            return CompletableFuture.completedFuture(unauthorized(Json.newObject()
                    .put("message", "The user is not authorized to perform this action!")
            ));
        }
    } else if(configuration.requireGuest()) {
        if(role.equals("guest") || role.equals("personnel") || role.equals("admin")) {
            return delegate.call(ctx);
        } else {
            return CompletableFuture.completedFuture(unauthorized(Json.newObject()
                    .put("message", "The user is not authorized to perform this action!")
            ));
        }
    }
    return CompletableFuture.completedFuture(unauthorized(Json.newObject()
            .put("message", "an error occurred")
    ));

}

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM