我正在尝试使用App Engine制作Android应用程序作为移动后端。 当我尝试调用受身份验证保护的端点时,我收到此错误:
12-21 18:58:05.120 4452-4477/com.test.myapplication W/System.err﹕ com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
12-21 18:58:05.120 4452-4477/com.test.myapplication W/System.err﹕ {
12-21 18:58:05.130 4452-4477/com.test.myapplication W/System.err﹕ {
12-21 18:58:05.130 4452-4477/com.test.myapplication W/System.err﹕ "domain": "global",
12-21 18:58:05.130 4452-4477/com.test.myapplication W/System.err﹕ "location": "Authorization",
12-21 18:58:05.130 4452-4477/com.test.myapplication W/System.err﹕ "locationType": "header",
12-21 18:58:05.130 4452-4477/com.test.myapplication W/System.err﹕ "message": "Authorization required",
12-21 18:58:05.130 4452-4477/com.test.myapplication W/System.err﹕ "reason": "required"
12-21 18:58:05.130 4452-4477/com.test.myapplication W/System.err﹕ }
12-21 18:58:05.130 4452-4477/com.test.myapplication W/System.err﹕ ],
12-21 18:58:05.130 4452-4477/com.test.myapplication W/System.err﹕ "message": "Authorization required"
12-21 18:58:05.130 4452-4477/com.test.myapplication W/System.err﹕ }
12-21 18:58:05.130 4452-4477/com.test.myapplication W/System.err﹕ at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
12-21 18:58:05.130 4452-4477/com.test.myapplication W/System.err﹕ at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
12-21 18:58:05.130 4452-4477/com.test.myapplication W/System.err﹕ at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:312)
以下是App Engine上的端点代码
@ApiMethod(
name = "signInWithGoogle",
path = "signInWithGoogle",
httpMethod = ApiMethod.HttpMethod.POST
)
public Profile signInWithGoogle(final User user) throws UnauthorizedException {
if (user == null) {
throw new UnauthorizedException("Authorization required");
}
Key<Profile> profileKey = Key.create(Profile.class, user.getEmail());
return OfyService.ofy().load().key(profileKey).now();
}
这是调用端点的活动代码
public class MainActivity extends Activity {
public static final String WEB_CLIENT_ID = "XXXX.apps.googleusercontent.com";
public static final String AUDIENCE = "server:client_id:" + WEB_CLIENT_ID;
protected static final HttpTransport HTTP_TRANSPORT = AndroidHttp.newCompatibleTransport();
protected static final JsonFactory JSON_FACTORY = new AndroidJsonFactory();
GoogleAccountCredential credential;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
credential = GoogleAccountCredential.usingAudience(this, AUDIENCE);
startActivityForResult(credential.newChooseAccountIntent(), 0);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
String accountName = data.getExtras().getString(AccountManager.KEY_ACCOUNT_NAME);
credential.setSelectedAccountName(accountName);
final SignUser signUser = new SignUser.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential).build();
Log.d("TEST", "start");
new Thread(new Runnable() {
@Override
public void run() {
try {
Profile profile = signUser.signInWithGoogle().execute();
Log.d("TEST", "success");
} catch (IOException e) {
e.printStackTrace();
Log.d("TEST", "failed");
}
}
}).start();
}
}
似乎signUser.signInWithGoogle().execute()
不会创建端点需要的User对象,因此,端点会抛出UnauthorizedException。
实际上,如果我从端点删除OAuth2保护,一切正常。
有人能解释一下我的错误是什么吗?
更新
这是java类的@Api注释。
@Api(
name = "signUser",
version = "v1",
scopes = {Constants.EMAIL_SCOPE},
clientIds = {Constants.ANDROID_CLIENT_ID, Constants.API_EXPLORER_CLIENT_ID},
audiences = {Constants.ANDROID_AUDIENCE},
description = "APIs for sign user"
)
其中EMAIL_SCOPE
是https://www.googleapis.com/auth/userinfo.email
并且ANDROID_AUDIENCE
等于WEB_CLIENT_ID
答案 0 :(得分:3)
我通过将自定义请求初始化程序设置为凭据对象(如此
)来解决此问题GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(this.TRANSPORT).setJsonFactory(this.JSON_FACTORY)
.setClientSecrets(Constants.CLIENT_ID, Constants.CLIENT_SECRET).setRequestInitializer((new HttpRequestInitializer(){
@Override
public void initialize(HttpRequest request)
throws IOException {
request.getHeaders().put("Authorization", "Bearer " + accessToken);
}
})).build()