mar*_*ars 8 java authentication amazon-web-services aws-java-sdk
我搜索了很多,但似乎无法从头到尾找到解决方案.作为前提,我已经在iOS和Android的两个原生应用程序中实现了Cognito注册,登录和刷新凭证,因此我已经开发了(至少)对身份验证流程的基本了解.
这些移动应用程序使用最简单的Cognito设置:用户池,具有IAM角色的身份池,用于经过身份验证的用户,并且不会使用任何未经身份验证的使用.我没有使用(至少现在)Facebook,谷歌或亚马逊登录,也没有其他身份验证方法.
现在我需要用Java制作这些应用程序的桌面版本,在我看来它是一个完全不同的野兽.我想做的是:
实现这一目标的方法在纸面上相当简单:
在阅读了大量文档,下载了许多不同的项目示例和大量的绝望之后,我终于找到了在移动应用程序中实现这一点的方法.例如,在Android中,身份验证流程的工作方式如下:
与Java SDK实现相同的功能在我看来要困难得多.
我设法很容易地实现用户注册.但是,如果用户登录,我根本不知道从哪里开始.
每个例子都以不同的方式做到这一点.最重要的是,每个示例都使用特定用例,例如开发人员验证的Sign-Ins或自定义URL来连接到某个拥有的后端.为什么如此难以找到像我需要的基本用例的例子?我开始认为我的基本用例根本不是基本的,而是非典型的.为什么使用用户名和密码登录AWS的默认用户/凭证服务是非典型的,但是,我真的不知道.
到目前为止,我所做的最好的是从这个示例项目中复制相关的类(我还从中获取了注册部分,它运行良好)并在控制台中打印IdToken,AccessToken和RefreshToken.它们打印正确且不为空.我真正理解的是如何获取凭据并将其添加到凭证提供程序,以便实例化客户端以访问其他AWS服务.我在项目中看到的唯一方法就是调用方法
Credentials getCredentials(String accessCode)
我想它应该接受使用InitAuth方法检索的访问代码(启动OAuth2.0身份验证流程,如果我错了请纠正我).问题是我找不到检索该代码的方法.我找不到访问代码的在线示例来查看它的外观.我试图将其中一个令牌和Web请求做出响应
{"error":"invalid_grant"}
Run Code Online (Sandbox Code Playgroud)
这表明它不是有效的代码,但至少Web请求是有效的.
为了更清楚,我能做的是:
String username; //retrieved from UI
String password; //retrieved from UI
//I copied AuthenticationHelper as is from the project
AuthenticationHelper helper = new AuthenticationHelper(POOL_ID, CLIENT_APP_ID, CLIENT_SECRET);
//I then retrieve the tokens with SRP authentication
AuthenticationResultType result = helper.performSRPAuthentication(username, password);
//Now I can successfully print the tokens, for example:
System.out.println(result.getAccessToken());
Run Code Online (Sandbox Code Playgroud)
如何从此处检索凭据?我应该把身份池ID放在哪里?在Android中,我只是将JWT令牌添加到一个HashMap并使用它
credentialsProvider.setLogins(loginsMap).
此外,这个项目包含有数百行代码的类,BigInteger变量,多行随机字符的硬编码字符串(我认为某种键或令牌)和其他类似的黑魔法(特别是在AuthenticationHelper类中).我不喜欢这个解决方案的另一件事是它通过手动编写的Web请求检索凭证(另一个分离的类是临时创建的以生成请求).Java SDK中真的不存在一些方便的方法,它将所有这些东西包装在一堆优雅的代码行中吗?为什么称它为SDK而不是?iOS和Android SDK以这种更简单的方式处理所有这些问题.这是因为他们希望台式机应用程序的开发人员更有能力/专家,而有一天,从床上起床的普通人决定制作iOS/Android应用程序[暗示自己]?这可以解释他们努力使移动SDK比较适合开发人员.
我发现很难相信我必须这样做,阅读谁知道在哪个文档页面知道哪里,登录用户,这让我觉得我真的错过了什么.我真的读了我能找到的每个堆栈交换问题和文档.事实上,几乎总有一个AWS文档页面可以满足我的需求,但实际上有时候发现它并不是那么简单,至少对于Cognito文档而言.
我读到我可以在PC文件系统中放置一个带有所需凭据的文件,Java SDK将使用这些凭据来访问所有资源,但是根据我的理解,这个方法保留给在服务器上作为后端运行的Java应用程序(servlets) ),最终用户无法通过他的浏览器访问它们.我的应用程序是面向最终用户的桌面应用程序,所以我甚至不能考虑在用户PC上保留AWS凭据(如果我错了,请纠正我,我真的很想做一些如此简单的事情).
真正令我害怕的是,可能根本无法使用用户池和身份池进行登录.我知道Cognito相关的东西已被添加到Java SDK中,后来它可用于iOS,Android和JavaScript.但是,如果他们添加它,我认为它应该支持至少类似于移动对应的认证流程.
更糟糕的是,我最初使我的应用程序的所有功能都脱机工作.我以为我最终会在应用程序中集成AWS.通过这种方式,应用程序更加模块化,并且AWS相关的东西集中在一个包中,与其他应用程序逻辑和UI分离.在我无知的海洋中,这对我来说似乎是一种很好的做法,但是现在,如果我无法解决这个问题,我已经在垃圾桶中投入了数月的工作,只是意识到我必须建立一个网络应用程序,因为JavaScript是更多支持.
即使在MobileHub上,在Cognito上创建ClientApp的唯一选择是iOS,Android,JavaScript和React.当为其他语言/ SDK提供文档或示例时,通常会省略Java,我在选项中看到的最常见的是.NET.为了让我的挫折感更大,每当我在搜索引擎上搜索某些东西时,"Java"这个词包含在"JavaScript"这个词中的事实会混淆一些可能有用的结果,因为所有JavaScript SDK相关的东西通常都是在搜索引擎中排名比Java更高(这可以解释为什么.NET相关的东西似乎更容易找到,至少在StackOverflow或其他Q&A网站上).
总而言之,所有这些都在我脑海中产生了一些问题:
为什么这么少的人似乎需要这种身份验证方法(使用用户名和密码)?在我看来,桌面应用程序是一个非常常见和合理的用例.我知道Web应用程序的增长是通过顶层的,但鉴于Java是当今使用最多的语言之一,如何才有可能没有人需要从桌面应用程序进行简单的登录?这导致了下一个问题:
将Java SDK用于桌面应用程序时,是否存在固有的错误/错误/风险/愚蠢行为?它仅用于作为后端或Web应用程序在服务器上使用吗?制作连接到AWS服务的桌面应用程序应该是什么解决方案?完全使用AWS连接的桌面应用程序是错误的吗?Web应用程序应该考虑的唯一选择吗?为什么?我选择Java来实现一个可以在Widows,macOS和Linux上运行的应用程序.我也选择了Java,因为我认为它的用法大部分与Android SDK类似,因为它的代码应该与平台UI无关,因此可以简单地重用代码.我错了.
如果像这样使用Java SDK没有任何问题,请帮助我找一个将用户名和密码放在两个字段中的示例,并实例化客户端以访问其他AWS服务(例如S3客户端) )在Java桌面应用程序中?
告诉我你需要知道的一切,我会编辑这个问题.
请有人帮助我,我正在失去理智.
对于 OP 来说可能为时已晚,但这是我在获取 JWT 身份令牌后从 Cognito 获取凭证的过程。通过 SRP 身份验证获得 JWT 后,我使用联合池 ID 并传递 Cognito Idp Url 和 JWT 的登录映射来获取身份 ID。该 URL 由您的 aws 区域和您的 Cognito 用户池 ID 组成。
//create a Cognito provider with anonymous creds
AnonymousAWSCredentials awsCreds = new AnonymousAWSCredentials();
AmazonCognitoIdentity provider = AmazonCognitoIdentityClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.withRegion(REGION)
.build();
//get the identity id using the login map
String idpUrl = String.format("cognito-idp.%s.amazonaws.com/%s", REGION, cognitoUserPoolId);
GetIdRequest idrequest = new GetIdRequest();
idrequest.setIdentityPoolId(FED_POOL_ID);
idrequest.addLoginsEntry(idpUrl, jwt);
//use the provider to make the id request
GetIdResult idResult = provider.getId(idrequest);
return idResult.getIdentityId();
Run Code Online (Sandbox Code Playgroud)
如果您使用不同的登录提供程序,则该 url 需要更改,但这应该获取身份 ID。接下来是一个类似的请求,通过传递身份 ID 和相同的登录映射来获取 IAM 凭证。
//create a Cognito provider with anonymous creds
AnonymousAWSCredentials awsCreds = new AnonymousAWSCredentials();
AmazonCognitoIdentity provider = AmazonCognitoIdentityClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.withRegion(REGION)
.build();
//request authenticated credentials using the identity id and login map for authentication
String idpUrl = String.format("cognito-idp.%s.amazonaws.com/%s", REGION, cognitoUserPoolId);
GetCredentialsForIdentityRequest request = new GetCredentialsForIdentityRequest();
request.setIdentityId(identityId);
request.addLoginsEntry(idpUrl, jwt);
//use Cognito provider to perform credentials request
GetCredentialsForIdentityResult result = provider.getCredentialsForIdentity(request);
return result.getCredentials();
Run Code Online (Sandbox Code Playgroud)
这花了我整整一周的时间才弄清楚。在我看来,AWS Java 文档非常糟糕。希望这可以帮助别人。
| 归档时间: |
|
| 查看次数: |
1177 次 |
| 最近记录: |