Java 中的 Firebase 电子邮件+密码身份验证
Firebase email+password authentication in Java
我正在尝试使用他们的 REST API 在 Java 中使用 Firebase 电子邮件和密码身份验证,因为他们的 Admin SDK 不提供登录等所需的方法,只有用户管理方法。
在 this answer 的帮助下,我设法将以下代码放在一起,这些代码适用于正确的凭据,但在尝试处理错误时,例如USER_NOT_FOUND 或 INVALID_PASSWORD,我得到的只是 java.io.IOException,其中包含详细信息 Server returned HTTP response code: 400 for URL: https://www.googleapis.com/identitytoolkit/v3/relyingparty/getAccountInfo?key=key
。
package com.amansprojects.craftclaw;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
public class FirebaseAuthManager {
private static final String BASE_URL = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/";
private static final String OPERATION_AUTH = "verifyPassword";
private static final String OPERATION_ACCOUNT_INFO = "getAccountInfo";
private String firebaseKey;
private static FirebaseAuthManager instance = null;
protected FirebaseAuthManager() {
firebaseKey = "MY_KEY_HERE";
}
public static FirebaseAuthManager getInstance() {
if (instance == null) {
instance = new FirebaseAuthManager();
}
return instance;
}
public String auth(String username, String password) {
HttpURLConnection urlRequest = null;
String token = null;
try {
URL url = new URL(BASE_URL + OPERATION_AUTH + "?key=" + firebaseKey);
urlRequest = (HttpURLConnection) url.openConnection();
urlRequest.setDoOutput(true);
urlRequest.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
OutputStream os = urlRequest.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
osw.write("{\"email\": \"" + username + "\", \"password\": \"" + password + "\", \"returnSecureToken\": true}");
osw.flush();
osw.close();
urlRequest.connect();
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader((InputStream) urlRequest.getContent()));
JsonObject rootObj = root.getAsJsonObject();
token = rootObj.get("idToken").getAsString();
System.out.println(rootObj); // debugging
} catch (IOException e) { e.printStackTrace(); return null; }
finally { urlRequest.disconnect(); }
return token;
}
public String getAccountInfo(String token) {
HttpURLConnection urlRequest = null;
String email = null;
try {
URL url = new URL(BASE_URL + OPERATION_ACCOUNT_INFO + "?key=" + firebaseKey);
urlRequest = (HttpURLConnection) url.openConnection();
urlRequest.setDoOutput(true);
urlRequest.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
OutputStream os = urlRequest.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
osw.write("{\"idToken\": \"" + token + "\"}");
osw.flush();
osw.close();
urlRequest.connect();
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader((InputStream) urlRequest.getContent()));
JsonObject rootObj = root.getAsJsonObject();
email = rootObj.get("users").getAsJsonArray().get(0).getAsJsonObject().get("email").getAsString();
} catch (IOException e) { e.printStackTrace(); return null; }
finally { urlRequest.disconnect(); }
return email;
}
}
提前致谢。
编辑:我也尝试过 Firebase 在其文档页面上显示的其他 domain/endpoint 组合:https://identitytoolkit.googleapis.com/v1/accounts:endpoint
在调试另一个问题时,我发现 Apache http 库不会针对 400 错误代码抛出 IOException,而是让您继续解析 JSON。
这是我在 Java 中与 class 接口的最终 Firebase Auth REST API。
package com.amansprojects.craftclaw;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
/**
* A class to interface with the Firebase Auth REST API.
*/
public class FirebaseAuthManager {
private static final String BASE_URL = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/";
private static final String OPERATION_AUTH = "verifyPassword";
private static final String OPERATION_ACCOUNT_INFO = "getAccountInfo";
private static final String OPERATION_SEND_PASSWORD_RESET = "getOobConfirmationCode";
private final String firebaseKey;
private static FirebaseAuthManager instance = null;
protected FirebaseAuthManager() {
firebaseKey = "YOUR_KEY_HERE";
}
public static FirebaseAuthManager getInstance() {
if (instance == null) {
instance = new FirebaseAuthManager();
}
return instance;
}
/**
* Exchange an email and password with the Firebase Auth REST API for an ID token.
* @param username A username or email registered with Firebase Authentication.
* @param password The password associated with the username or email.
* @return An ID token from Firebase.
* @throws FirebaseAuthException
*/
public String auth(String username, String password) throws FirebaseAuthException {
String token;
try {
HttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost(BASE_URL + OPERATION_AUTH + "?key=" + firebaseKey);
List<NameValuePair> params = new ArrayList<NameValuePair>(1);
params.add(new BasicNameValuePair("email", username));
params.add(new BasicNameValuePair("password", password));
params.add(new BasicNameValuePair("returnSecureToken", "true"));
httppost.setEntity(new UrlEncodedFormEntity(params, StandardCharsets.UTF_8));
HttpEntity entity = httpclient.execute(httppost).getEntity();
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader(entity.getContent()));
JsonObject rootObj = root.getAsJsonObject();
if (rootObj.get("error") != null) {
throw new FirebaseAuthException(rootObj.get("error").getAsJsonObject().get("message").getAsString());
}
token = rootObj.get("idToken").getAsString();
} catch (IOException e) { System.out.println(e.getMessage()); return null; }
return token;
}
/**
* Exchange an ID token with the Firebase Auth REST API for a User object.
* @param token An ID token from Firebase.
* @return A user object with the email and UID returned by Firebase.
*/
public User getAccountInfo(String token) {
try {
HttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost(BASE_URL + OPERATION_ACCOUNT_INFO + "?key=" + firebaseKey);
List<NameValuePair> params = new ArrayList<NameValuePair>(1);
params.add(new BasicNameValuePair("idToken", token));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
HttpEntity entity = httpclient.execute(httppost).getEntity();
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader(entity.getContent()));
JsonObject rootObj = root.getAsJsonObject();
JsonObject userObj = rootObj.get("users").getAsJsonArray().get(0).getAsJsonObject();
return new User(userObj.get("email").getAsString(), userObj.get("localId").getAsString(), token);
} catch (IOException e) { System.out.println(e.getMessage()); return null; }
}
/**
* Send a reset password email via Firebase.
* @param email The email address to send the reset password email to.
*/
public void sendResetPasswordLink(String email) {
try {
HttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost(BASE_URL + OPERATION_SEND_PASSWORD_RESET + "?key=" + firebaseKey);
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(new BasicNameValuePair("requestType", "PASSWORD_RESET"));
params.add(new BasicNameValuePair("email", email));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
httpclient.execute(httppost);
} catch (IOException e) { e.printStackTrace(); }
}
/**
* Exchange a refresh token with the Firebase Auth REST API for a new ID token.
* @param refreshToken The refresh token used to receive an ID token.
* @return A new ID token from Firebase.
*/
public String[] exchangeRefreshToken(String refreshToken) {
try {
HttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost("https://securetoken.googleapis.com/v1/token?key="+ firebaseKey);
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(new BasicNameValuePair("grant_type", "refresh_token"));
params.add(new BasicNameValuePair("refresh_token", refreshToken));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
HttpEntity entity = httpclient.execute(httppost).getEntity();
if (entity != null) {
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader(entity.getContent()));
JsonObject rootObj = root.getAsJsonObject();
return new String[]{ rootObj.get("id_token").getAsString(), rootObj.get("refresh_token").getAsString() };
}
} catch (IOException e) { e.printStackTrace(); }
return null;
}
}
我正在尝试使用他们的 REST API 在 Java 中使用 Firebase 电子邮件和密码身份验证,因为他们的 Admin SDK 不提供登录等所需的方法,只有用户管理方法。
在 this answer 的帮助下,我设法将以下代码放在一起,这些代码适用于正确的凭据,但在尝试处理错误时,例如USER_NOT_FOUND 或 INVALID_PASSWORD,我得到的只是 java.io.IOException,其中包含详细信息 Server returned HTTP response code: 400 for URL: https://www.googleapis.com/identitytoolkit/v3/relyingparty/getAccountInfo?key=key
。
package com.amansprojects.craftclaw;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
public class FirebaseAuthManager {
private static final String BASE_URL = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/";
private static final String OPERATION_AUTH = "verifyPassword";
private static final String OPERATION_ACCOUNT_INFO = "getAccountInfo";
private String firebaseKey;
private static FirebaseAuthManager instance = null;
protected FirebaseAuthManager() {
firebaseKey = "MY_KEY_HERE";
}
public static FirebaseAuthManager getInstance() {
if (instance == null) {
instance = new FirebaseAuthManager();
}
return instance;
}
public String auth(String username, String password) {
HttpURLConnection urlRequest = null;
String token = null;
try {
URL url = new URL(BASE_URL + OPERATION_AUTH + "?key=" + firebaseKey);
urlRequest = (HttpURLConnection) url.openConnection();
urlRequest.setDoOutput(true);
urlRequest.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
OutputStream os = urlRequest.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
osw.write("{\"email\": \"" + username + "\", \"password\": \"" + password + "\", \"returnSecureToken\": true}");
osw.flush();
osw.close();
urlRequest.connect();
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader((InputStream) urlRequest.getContent()));
JsonObject rootObj = root.getAsJsonObject();
token = rootObj.get("idToken").getAsString();
System.out.println(rootObj); // debugging
} catch (IOException e) { e.printStackTrace(); return null; }
finally { urlRequest.disconnect(); }
return token;
}
public String getAccountInfo(String token) {
HttpURLConnection urlRequest = null;
String email = null;
try {
URL url = new URL(BASE_URL + OPERATION_ACCOUNT_INFO + "?key=" + firebaseKey);
urlRequest = (HttpURLConnection) url.openConnection();
urlRequest.setDoOutput(true);
urlRequest.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
OutputStream os = urlRequest.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
osw.write("{\"idToken\": \"" + token + "\"}");
osw.flush();
osw.close();
urlRequest.connect();
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader((InputStream) urlRequest.getContent()));
JsonObject rootObj = root.getAsJsonObject();
email = rootObj.get("users").getAsJsonArray().get(0).getAsJsonObject().get("email").getAsString();
} catch (IOException e) { e.printStackTrace(); return null; }
finally { urlRequest.disconnect(); }
return email;
}
}
提前致谢。
编辑:我也尝试过 Firebase 在其文档页面上显示的其他 domain/endpoint 组合:https://identitytoolkit.googleapis.com/v1/accounts:endpoint
在调试另一个问题时,我发现 Apache http 库不会针对 400 错误代码抛出 IOException,而是让您继续解析 JSON。
这是我在 Java 中与 class 接口的最终 Firebase Auth REST API。
package com.amansprojects.craftclaw;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
/**
* A class to interface with the Firebase Auth REST API.
*/
public class FirebaseAuthManager {
private static final String BASE_URL = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/";
private static final String OPERATION_AUTH = "verifyPassword";
private static final String OPERATION_ACCOUNT_INFO = "getAccountInfo";
private static final String OPERATION_SEND_PASSWORD_RESET = "getOobConfirmationCode";
private final String firebaseKey;
private static FirebaseAuthManager instance = null;
protected FirebaseAuthManager() {
firebaseKey = "YOUR_KEY_HERE";
}
public static FirebaseAuthManager getInstance() {
if (instance == null) {
instance = new FirebaseAuthManager();
}
return instance;
}
/**
* Exchange an email and password with the Firebase Auth REST API for an ID token.
* @param username A username or email registered with Firebase Authentication.
* @param password The password associated with the username or email.
* @return An ID token from Firebase.
* @throws FirebaseAuthException
*/
public String auth(String username, String password) throws FirebaseAuthException {
String token;
try {
HttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost(BASE_URL + OPERATION_AUTH + "?key=" + firebaseKey);
List<NameValuePair> params = new ArrayList<NameValuePair>(1);
params.add(new BasicNameValuePair("email", username));
params.add(new BasicNameValuePair("password", password));
params.add(new BasicNameValuePair("returnSecureToken", "true"));
httppost.setEntity(new UrlEncodedFormEntity(params, StandardCharsets.UTF_8));
HttpEntity entity = httpclient.execute(httppost).getEntity();
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader(entity.getContent()));
JsonObject rootObj = root.getAsJsonObject();
if (rootObj.get("error") != null) {
throw new FirebaseAuthException(rootObj.get("error").getAsJsonObject().get("message").getAsString());
}
token = rootObj.get("idToken").getAsString();
} catch (IOException e) { System.out.println(e.getMessage()); return null; }
return token;
}
/**
* Exchange an ID token with the Firebase Auth REST API for a User object.
* @param token An ID token from Firebase.
* @return A user object with the email and UID returned by Firebase.
*/
public User getAccountInfo(String token) {
try {
HttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost(BASE_URL + OPERATION_ACCOUNT_INFO + "?key=" + firebaseKey);
List<NameValuePair> params = new ArrayList<NameValuePair>(1);
params.add(new BasicNameValuePair("idToken", token));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
HttpEntity entity = httpclient.execute(httppost).getEntity();
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader(entity.getContent()));
JsonObject rootObj = root.getAsJsonObject();
JsonObject userObj = rootObj.get("users").getAsJsonArray().get(0).getAsJsonObject();
return new User(userObj.get("email").getAsString(), userObj.get("localId").getAsString(), token);
} catch (IOException e) { System.out.println(e.getMessage()); return null; }
}
/**
* Send a reset password email via Firebase.
* @param email The email address to send the reset password email to.
*/
public void sendResetPasswordLink(String email) {
try {
HttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost(BASE_URL + OPERATION_SEND_PASSWORD_RESET + "?key=" + firebaseKey);
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(new BasicNameValuePair("requestType", "PASSWORD_RESET"));
params.add(new BasicNameValuePair("email", email));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
httpclient.execute(httppost);
} catch (IOException e) { e.printStackTrace(); }
}
/**
* Exchange a refresh token with the Firebase Auth REST API for a new ID token.
* @param refreshToken The refresh token used to receive an ID token.
* @return A new ID token from Firebase.
*/
public String[] exchangeRefreshToken(String refreshToken) {
try {
HttpClient httpclient = HttpClients.createDefault();
HttpPost httppost = new HttpPost("https://securetoken.googleapis.com/v1/token?key="+ firebaseKey);
List<NameValuePair> params = new ArrayList<NameValuePair>(2);
params.add(new BasicNameValuePair("grant_type", "refresh_token"));
params.add(new BasicNameValuePair("refresh_token", refreshToken));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
HttpEntity entity = httpclient.execute(httppost).getEntity();
if (entity != null) {
JsonParser jp = new JsonParser();
JsonElement root = jp.parse(new InputStreamReader(entity.getContent()));
JsonObject rootObj = root.getAsJsonObject();
return new String[]{ rootObj.get("id_token").getAsString(), rootObj.get("refresh_token").getAsString() };
}
} catch (IOException e) { e.printStackTrace(); }
return null;
}
}