有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Amazon Cognito中的java开发者身份验证

我试图遵循thisthis教程,但我不确定这是否应该这样做。我使用的是CognitoSync,当我尝试启动同步服务时,我遇到了“标识和数据集名称不唯一”的异常

在Amazon控制台上,我创建了一个IdentityPool,并将服务器端类的包名命名为DeveloperProvider,即“com.leversystems.devauth”,并将其用于服务器类和Android应用程序。 在服务器类中

map.put("com.leversystems.devauth", "someUniqueId");

在Android应用程序中

logins.put("com.leversystems.devauth", cognitoProvider.getToken());

这是我的代码

Java服务器端

package com.leversystems.devauth;
import java.util.HashMap;

import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.cognitoidentity.AmazonCognitoIdentityClient;
import com.amazonaws.services.cognitoidentity.model.GetOpenIdTokenForDeveloperIdentityRequest;
import com.amazonaws.services.cognitoidentity.model.GetOpenIdTokenForDeveloperIdentityResult;

public class DevAuth {

    private BasicAWSCredentials credentials = null;

    private String myAwsAccessKey = "myaccesskey";
    private String myAwsSecretKey = "mysecretkey";
    private String identityPoolID = "identityPoolid";
    private String authARN = "arn:aws:iam::782936514542:role/DefaultRole";

    private String identityId;
    private String token;

    public DevAuth()
    {
        identityId = "No id has been set yet!";
        token = "No token has been set yet!";
        initializeSecurity();
    }

    public String getToken()
    {
        return this.token;
    }

    public String getIdentityId()
    {
        return this.identityId;     
    }

    public void initializeSecurity(){

        credentials = new BasicAWSCredentials(myAwsAccessKey , myAwsSecretKey);
        AmazonCognitoIdentityClient client = 
          new AmazonCognitoIdentityClient(credentials);
        GetOpenIdTokenForDeveloperIdentityRequest tokenRequest = 
          new GetOpenIdTokenForDeveloperIdentityRequest();
        tokenRequest.setIdentityPoolId(identityPoolID);
        HashMap<String, String> map = new HashMap<String, String>();

        map.put("com.leversystems.devauth", "nameid.number@provider.com");

        //Duration of the generated OpenID Connect Token
        tokenRequest.setLogins(map);

        tokenRequest.setTokenDuration(1000l);

        GetOpenIdTokenForDeveloperIdentityResult result 
           = client.getOpenIdTokenForDeveloperIdentity(tokenRequest);
        this.identityId = result.getIdentityId();
        this.token = result.getToken();
    }}

我已经为这个类创建了一个Web服务,在另一个类桥类中,我调用了这个函数,它将令牌和id发送到Android应用程序。这工作正常,我在Android应用程序中获得了Token和IdentityId

安卓类

主要活动类

package com.leversystems.authserver;

import java.util.HashMap;
import java.util.List;

import 安卓.app.Activity;
import 安卓.os.Bundle;
import 安卓.os.StrictMode;
import 安卓.util.Log;
import 安卓.view.View;
import 安卓.widget.Button;
import 安卓.widget.TextView;
import 安卓.widget.Toast;

import com.amazonaws.auth.AWSCognitoIdentityProvider;
import com.amazonaws.auth.CognitoCachingCredentialsProvider;
import com.amazonaws.mobileconnectors.cognito.CognitoSyncManager;
import com.amazonaws.mobileconnectors.cognito.Dataset;
import com.amazonaws.mobileconnectors.cognito.Dataset.SyncCallback;
import com.amazonaws.mobileconnectors.cognito.Record;
import com.amazonaws.mobileconnectors.cognito.SyncConflict;
import com.amazonaws.mobileconnectors.cognito.exceptions.DataStorageException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.cognitoidentity.AmazonCognitoIdentity;
import com.amazonaws.services.cognitoidentity.model.GetOpenIdTokenForDeveloperIdentityRequest;
import com.amazonaws.services.cognitoidentity.model.GetOpenIdTokenForDeveloperIdentityResult;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.loopj.安卓.http.AsyncHttpClient;
import com.loopj.安卓.http.AsyncHttpResponseHandler;

public class MainActivity extends Activity {

AWSCognitoIdentityProvider cognitoProvider;
CognitoCachingCredentialsProvider credentialsProvider;
AmazonCognitoIdentity identityClient;
GetOpenIdTokenForDeveloperIdentityRequest idRequest;
GetOpenIdTokenForDeveloperIdentityResult idResp;
CognitoSyncManager client;

Dataset dataset;
TextView tv1;
TextView tv2;
TextView tv3;

Button btn1;
Button btn2;

final String ACC_ID = "myAccountID";
final String IDENTITY_POOL_ID = "identityPoolId";
final String AUTHORIZATION_ARN = "DefaultRole";
final String ACCESS_KEY = "myAccessKey";
final String SECRET_KEY = "mySecretKey";

Credentials cred;

public class Credentials {
    String identityId;
    String token;
}

            @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    playerName = (TextView) findViewById(R.id.textView1);
    currentLevel = (TextView) findViewById(R.id.textView2);
    highScore = (TextView) findViewById(R.id.textView3);

    btn1 = (Button) findViewById(R.id.button1);
    btn2 = (Button) findViewById(R.id.button2);
    btn3 = (Button) findViewById(R.id.button3);

    initCognito();

    btn1.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
            displayCogntioSyncData();
        }
    });

    btn2.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
            addCognitoSyncData();
        }
    });

    btn3.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            wipeCognitoSyncData();
        }
    });

}

private void initCognito() {

    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
            .permitAll().build();
    StrictMode.setThreadPolicy(policy);

    AsyncHttpClient client = new AsyncHttpClient();
    client.get(
            "http://192.168.1.112:8080/AuthenticationService/services/auth/gctbda",
            new AsyncHttpResponseHandler() {
                // When the response returned by REST has Http response code
                // '200'
                @Override
                public void onSuccess(String response) {
                    try {
                        Gson gson = new Gson();
                        JsonParser jsonParser = new JsonParser();
                        JsonArray resultArray = jsonParser.parse(response)
                                .getAsJsonArray();

                        for (JsonElement credProvider : resultArray) {
                            cred = gson.fromJson(credProvider,
                                    Credentials.class);
                            BYOIProvider.identityId = cred.identityId;
                            BYOIProvider.token = cred.token;
                            System.out.println("Id: " + cred.identityId);
                            System.out.println("Token: " + cred.token);
                        }
                        syncCognito();
                    } catch (Exception e) {
                        System.err.println("Exception in OnSuccess: "
                                + e.getMessage());
                    }
                }
            });
}

private void syncCognito() {

    cognitoProvider = new BYOIProvider(ACC_ID, IDENTITY_POOL_ID);


    credentialsProvider = new CognitoCachingCredentialsProvider(
            getApplicationContext(), cognitoProvider, null,
            AUTHORIZATION_ARN);

    cognitoProvider.refresh();

    HashMap<String, String> logins = new HashMap<String, String>();

    logins.put("com.leversystems.devauth", cognitoProvider.getToken());

    credentialsProvider.setLogins(logins);

    credentialsProvider.refresh();

    client = new CognitoSyncManager(getApplicationContext(),
            IDENTITY_POOL_ID, Regions.US_EAST_1, credentialsProvider);

    dataset = client.openOrCreateDataset("GameInfo");

    synchronize();
}

private void wipeCognitoSyncData() {
    client.wipeData();
    dataset.delete();
    synchronize();
}

private void addCognitoSyncData() {

    dataset.put("playerName", "Muneeb");
    dataset.put("currentLevel", "29");
    dataset.put("highScore", "120345");

    synchronize();

}

private void displayCogntioSyncData() {
    synchronize();

    playerName.setText(dataset.get("playerName"));
    currentLevel.setText(dataset.get("currentLevel"));
    highScore.setText(dataset.get("highScore"));

}

private void synchronize() {

    dataset.synchronize(new SyncCallback() {

        @Override
        public boolean onConflict(Dataset arg0, List<SyncConflict> arg1) {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean onDatasetDeleted(Dataset arg0, String arg1) {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public boolean onDatasetsMerged(Dataset arg0, List<String> arg1) {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public void onFailure(DataStorageException arg0) {
            System.err.println("Error onSyncro: " + arg0.getMessage());
        }

        @Override
        public void onSuccess(Dataset arg0, List<Record> arg1) {
            System.out.println("Dataset Synchronized!");
        }
    });

}
}

BYOIProvider类

package com.leversystems.authserver;

import com.amazonaws.auth.AWSAbstractCognitoIdentityProvider;

public class BYOIProvider extends AWSAbstractCognitoIdentityProvider {

    public static String id;
    public static String token;


    public BYOIProvider(String acctId, String identityPoolId) {
        super(acctId, identityPoolId);

    }

    @Override
    public String getProviderName() {

        return "com.leversystems.devauth";
    }

    @Override
    public String refresh() {
        update(id, token);
        return null;
    }
}

工作流程

  1. 在安卓应用程序中,当点击按钮时,getCredentials()被调用,它从Java服务器类获取令牌和id
  2. 然后将令牌和Id传递给BYOIProvider类以更新它们
  3. 调用syncData(),初始化CognitoCredentialProvider和BYOIProvider变量
  4. CognitoSyncManager由CognitoCredentialProvider的对象初始化
  5. 在此之后,我收到一个异常错误

columns identity_id and dataset_name are not unique

在这行代码上

dataset = client.openOrCreateDataset("MyData");

Update-1(2014年11月11日)

好的,我现在已经将refresh()的返回字符串更改为token变量,这是stacktrace

11-11 12:58:52.196: I/View(29237): Touch down dispatch to 安卓.widget.Button{4186d880 VFED..C. ........ 206,342-417,438 #7f080003 app:id/button1}, event = MotionEvent { action=ACTION_DOWN, id[0]=0, x[0]=76.0, y[0]=34.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=228482273, downTime=228482273, deviceId=2, source=0x1002 }
11-11 12:58:52.213: D/GraphicBuffer(29237): create handle(0x5ed83e60) (w:720, h:1280, f:1)
11-11 12:58:52.222: I/SurfaceTextureClient(29237): [STC::queueBuffer] (this:0x5d12eb78) fps:0.10, dur:20282.80, max:20162.90, min:119.90
11-11 12:58:52.222: I/SurfaceTextureClient(29237): [STC::queueBuffer] this:0x5d12eb78, api:1, last queue time elapsed:20162.90
11-11 12:58:52.326: I/View(29237): Touch up dispatch to 安卓.widget.Button{4186d880 VFED..C. ...P.... 206,342-417,438 #7f080003 app:id/button1}, event = MotionEvent { action=ACTION_UP, id[0]=0, x[0]=76.0, y[0]=34.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=228482404, downTime=228482273, deviceId=2, source=0x1002 }
11-11 12:58:52.327: V/Provider/Settings(29237):  from settings cache , name = sound_effects_enabled , value = 0
11-11 12:58:52.328: D/dalvikvm(29237): create interp thread : stack size=128KB
11-11 12:58:52.328: D/dalvikvm(29237): create new thread
11-11 12:58:52.328: D/dalvikvm(29237): new thread created
11-11 12:58:52.328: D/dalvikvm(29237): update thread list
11-11 12:58:52.329: D/dalvikvm(29237): threadid=15: interp stack at 0x60115000
11-11 12:58:52.329: D/dalvikvm(29237): threadid=15: created from interp
11-11 12:58:52.329: D/dalvikvm(29237): start new thread
11-11 12:58:52.329: D/dalvikvm(29237): threadid=15: notify debugger
11-11 12:58:52.329: D/dalvikvm(29237): threadid=15 (RefQueueWorker@org.apache.http.impl.conn.tsccm.ConnPoolByRoute@419852e8): calling run()
11-11 12:58:52.330: I/System.out(29237): httpget:http://192.168.1.112:8080/AuthenticationService/services/auth/gctbda
11-11 12:58:52.331: I/System.out(29237): http://192.168.1.112:8080/AuthenticationService/services/auth/gctbda
11-11 12:58:52.331: D/dalvikvm(29237): create interp thread : stack size=128KB
11-11 12:58:52.331: D/dalvikvm(29237): create new thread
11-11 12:58:52.332: D/dalvikvm(29237): new thread created
11-11 12:58:52.332: D/dalvikvm(29237): update thread list
11-11 12:58:52.332: D/dalvikvm(29237): threadid=16: interp stack at 0x60235000
11-11 12:58:52.332: D/dalvikvm(29237): threadid=16: created from interp
11-11 12:58:52.332: D/dalvikvm(29237): start new thread
11-11 12:58:52.333: D/dalvikvm(29237): threadid=16: notify debugger
11-11 12:58:52.333: D/dalvikvm(29237): threadid=16 (pool-3-thread-1): calling run()
11-11 12:58:52.336: I/System.out(29237): [socket][1] connection /192.168.1.112:8080;LocalPort=35830(10000)
11-11 12:58:52.336: I/System.out(29237): [CDS]connect[/192.168.1.112:8080] tm:10
11-11 12:58:52.336: D/Posix(29237): [Posix_connect Debug]Process com.leversystems.authserver :8080 
11-11 12:58:52.358: I/System.out(29237): [socket][/192.168.1.136:35830] connected
11-11 12:58:52.358: I/System.out(29237): [CDS]rx timeout:10000
11-11 12:58:52.358: I/System.out(29237): [CDS]SO_SND_TIMEOUT:0
11-11 12:58:52.360: I/System.out(29237): >doSendRequest
11-11 12:58:52.361: I/System.out(29237): <doSendRequest
11-11 12:58:53.259: I/AmazonWebServiceClient(29237): {cognito-sync, us-east-1} was not found in region metadata, trying to construct an endpoint using the standard pattern for this region: 'cognito-sync.us-east-1.amazonaws.com'.
11-11 12:58:53.259: D/CognitoCachingCredentialsProvider(29237): Identity id is changed
11-11 12:58:53.259: D/CognitoCachingCredentialsProvider(29237): Saving identity id to SharedPreferences
11-11 12:58:53.260: I/CognitoSyncManager(29237): identity change detected
11-11 12:58:53.271: W/System.err(29237): Exception in OnSuccess: columns identity_id, dataset_name are not unique (code 19)

Update-2(2014年11月13日)

添加

credentialsProvider.refresh();

在setLogins()之后/withLogins()之后

现在,如果我尝试了一个错误的令牌,它会给出相应的异常。当我提供的代币是正确的,它会给我这个例外

Exception in onSuccess: Not authorized to perform sts:AssumeRoleWithWebIdentity (Service: AWSSecurityTokenService; Status Code: 403; Error Code: AccessDenied; Request ID: *SomeID*)

Update-3(2014年11月13日)

好的,我在IAM控制台上创建了一个新角色。Update-2中的异常现在已经清楚了。下一个问题与第一个问题相同。我在AsyncHttpClient内部收到的确切例外是

11-13 15:40:41.738: I/AmazonWebServiceClient(23921): {cognito-sync, us-east-1} was not found in region metadata, trying to construct an endpoint using the standard pattern for this region: 'cognito-sync.us-east-1.amazonaws.com'.
11-13 15:40:41.739: D/CognitoCachingCredentialsProvider(23921): Identity id is changed
11-13 15:40:41.739: D/CognitoCachingCredentialsProvider(23921): Saving identity id to SharedPreferences
11-13 15:40:41.740: I/CognitoSyncManager(23921): identity change detected
11-13 15:40:41.749: W/System.err(23921): Exception in OnSuccess: columns identity_id, dataset_name are not unique (code 19)

Update-4(2014年11月14日)

我的更新代码和StackTrace

代码:

credentialsProvider = new CognitoCachingCredentialsProvider(
            getApplicationContext(), cognitoProvider, null,
            AUTHORIZATION_ARN);

cognitoProvider.refresh();

StackTrace:

11-14 11:25:01.357: I/AmazonWebServiceClient(31084): {cognito-sync, us-east-1} was not found in region metadata, trying to construct an endpoint using the standard pattern for this region: 'cognito-sync.us-east-1.amazonaws.com'.
11-14 11:25:01.358: D/CognitoCachingCredentialsProvider(31084): Identity id is changed
11-14 11:25:01.358: D/CognitoCachingCredentialsProvider(31084): Saving identity id to SharedPreferences
11-14 11:25:01.358: I/CognitoSyncManager(31084): identity change detected
11-14 11:25:01.367: W/System.err(31084): Exception in OnSuccess: columns identity_id, dataset_name, key are not unique (code 19)

共 (1) 个答案

  1. # 1 楼答案

    正如杨帆所提到的,重要的是你要确保。refresh()返回标记,而不是null。CognitoCachingCredentialsProvider在内部调用它,并使用该令牌。理想情况下,与服务器的通信将在BYOIProvider类中进行,因为来自该类的方法调用将在CognitoCachingCredentialsProvider中使用

    更新电话很重要。它是通过并触发适当的身份更改处理(可能是导致您的问题的原因)和更新令牌的过程。它确实需要被调用,并且在这样做时具有适当的令牌和标识ID。如果您的getCredentials()调用在所有适当的时间都被使用,就足以确保它返回令牌,但是如果您要将与服务器通信的部分代码移动到刷新调用(更新上方)内部并更新返回,它将自行处理

    如果这不能解决你的问题,你能发布你的stacktrace吗

    编辑:

    好吧,我看到了另一种可能性。AWSAbstractCognitoIdentityProvider实际上会跟踪identityId和令牌——这些是凭据提供程序内部使用的。这可能意味着凭据提供程序没有获取您正在设置的标识ID和令牌。这些都可以通过getter和setter访问

    此外,在setLogins()/withLogins()的文档中,它表示在向凭据提供程序添加登录名后,您应该手动调用凭据提供程序上的刷新,因为您的身份id可能已更改。用户的身份id在从未经身份验证变为经过身份验证后会发生很大变化

    编辑2: 当一个身份发生变化时,会发生一些事情——其中之一是本地存储在数据库中的数据集,需要从与旧身份id的链接中删除,并添加到新身份id中。当身份更改的侦听器被激活时,会触发该操作。身份更改侦听器在初始化时注册到凭据提供程序,但在来自身份提供程序的更新调用时激活。这就是为什么顺序必须是它所做的,因此数据集用适当的标识id保存,并且避免了此错误

    错误本身可能由以下工作流引起: 1) 使用经过身份验证的标识b保存数据集a 2) 使用标识id c保存数据集a(很可能未经身份验证) 3) 身份验证返回到标识id b。这将把保存的数据集从c重新设置为b的父级,并导致出现非唯一错误

    因此,基本上,您必须确保在保存时使用适当的标识进行保存,以便对其进行适当处理