Firebase 服务帐户凭据 Json 读取权限被拒绝
Firebase Service Account Credentials Json Read permission denied
我从 Firebase 控制台下载了我的服务帐户凭据 json 文件,当我 运行 我在本地支持它时,它更早地放置在 GAE 端点项目的主目录中,它给出了安全异常。
java.security.AccessControlException: access denied ("java.io.FilePermission" "\src\main\secret.json" "read")
我也尝试将 .json 文件放在 src 目录下,但没有帮助。
您应该将 json 文件放在 src/main/resources
我找到了几种方法来解决这个问题。首先是通过 Internet 流从文件中获取它。另一个是本地的。
互联网方式
我的第一个方法是将文件存储在我的 public 保管箱文件夹中。我得到了可共享的 link(确保它以 .json
结尾)并将其粘贴到字符串示例 "https://dl.dropboxusercontent.com/..EXAMPLE-CREDENTIALS"
中
/** A simple endpoint method that takes a name and says Hi back */
@ApiMethod(name = "sayHi")
public MyBean sayHi(@Named("name") String name) {
MyBean mModelClassObject = null;
String text = "";
try {
String line = "";
StringBuilder builder = new StringBuilder();
URL url = new URL("https://dl.dropboxusercontent.com/..EXAMPLE-CREDENTIALS");
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
while ((line = reader.readLine()) != null) {
// ...
builder.append(line);
}
reader.close();
text = builder.toString();
} catch (MalformedURLException e) {
// ...
} catch (IOException e) {
// ...
}
InputStream stream = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
FirebaseOptions options = null;
options = new FirebaseOptions.Builder()
.setServiceAccount(stream)
.setDatabaseUrl("https://[PROJECT-ID].firebaseio.com/")
.build();
FirebaseApp.initializeApp(options);
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
final TaskCompletionSource<MyBean> tcs = new TaskCompletionSource<>();
Task<MyBean> tcsTask = tcs.getTask();
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
MyBean result = dataSnapshot.getValue(MyBean.class);
if(result != null){
tcs.setResult(result);
}
}
@Override
public void onCancelled(DatabaseError databaseError){
//handle error
}
});
try {
mModelClassObject = Tasks.await(tcsTask);
}catch(ExecutionException e){
//handle exception
}catch (InterruptedException e){
//handle exception
}
return mModelClassObject;
}
本地方式
另一种方法是采用上面的版本并跳过类似 dropbox 的东西
/** A simple endpoint method that takes a name and says Hi back */
@ApiMethod(name = "sayHi")
public MyBean sayHi(@Named("name") String name) {
MyBean mModelClassObject = null;
String text = "JUST PASTE YOUR JSON CONTENTS HERE";
InputStream stream = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
FirebaseOptions options = null;
options = new FirebaseOptions.Builder()
.setServiceAccount(stream)
.setDatabaseUrl("https://[PROJECT-ID].firebaseio.com/")
.build();
FirebaseApp.initializeApp(options);
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
final TaskCompletionSource<MyBean> tcs = new TaskCompletionSource<>();
Task<MyBean> tcsTask = tcs.getTask();
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
MyBean result = dataSnapshot.getValue(MyBean.class);
if(result != null){
tcs.setResult(result);
}
}
@Override
public void onCancelled(DatabaseError databaseError){
//handle error
}
});
try {
mModelClassObject = Tasks.await(tcsTask);
}catch(ExecutionException e){
//handle exception
}catch (InterruptedException e){
//handle exception
}
return mModelClassObject;
}
我不知道这是否符合最佳做法,但我的项目现在正在运行。
我还包含了用于获取信息的 firebase 代码。查看我最近询问的关于读写 firebase 的 的答案。
编辑
清理版本不会抛出错误
public class MyEndpoint {
private FirebaseOptions options;
private DatabaseReference ref;
private String serviceAccountJSON = "i took mine out for security reasons";
// create firebase instance if need be
private void connectToFirebase(){
if (options == null) {
options = null;
options = new FirebaseOptions.Builder()
.setServiceAccount(new ByteArrayInputStream(serviceAccountJSON.getBytes(StandardCharsets.UTF_8)))
.setDatabaseUrl("https://[PROJECT-ID].firebaseio.com/")
.build();
FirebaseApp.initializeApp(options);
}
if(ref == null) {
ref = FirebaseDatabase.getInstance().getReference();
}
}
/** A simple endpoint method that takes a name and says Hi back */
@ApiMethod(name = "sayHi")
public MyBean sayHi(@Named("name") String name) {
// always do this first
connectToFirebase();
MyBean mModelClassObject = null;
final TaskCompletionSource<MyBean> tcs = new TaskCompletionSource<>();
Task<MyBean> tcsTask = tcs.getTask();
// get the info
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
MyBean result = dataSnapshot.getValue(MyBean.class);
if(result != null){
tcs.setResult(result);
}
}
@Override
public void onCancelled(DatabaseError databaseError){
//handle error
}
});
// wait for it
try {
mModelClassObject = Tasks.await(tcsTask);
}catch(ExecutionException e){
//handle exception
}catch (InterruptedException e){
//handle exception
}
mModelClassObject.setData(mModelClassObject.getData() + name);
return mModelClassObject;
}
}
最后,我找到了解决方案,它写在 Google App Engine 的 APIs and references 部分下 link,我们需要在 appengine-[=16] 中添加这样的文件=] 文件在 <resource-files>
标签下,使用 <include path=""/>
属性。这样做之后它对我有用。我将包含项目凭据的 .json 文件放在 WEB-INF 目录中,然后在 <resource-files>
标记中输入其相对路径。
我从 Firebase 控制台下载了我的服务帐户凭据 json 文件,当我 运行 我在本地支持它时,它更早地放置在 GAE 端点项目的主目录中,它给出了安全异常。
java.security.AccessControlException: access denied ("java.io.FilePermission" "\src\main\secret.json" "read")
我也尝试将 .json 文件放在 src 目录下,但没有帮助。
您应该将 json 文件放在 src/main/resources
我找到了几种方法来解决这个问题。首先是通过 Internet 流从文件中获取它。另一个是本地的。
互联网方式
我的第一个方法是将文件存储在我的 public 保管箱文件夹中。我得到了可共享的 link(确保它以 .json
结尾)并将其粘贴到字符串示例 "https://dl.dropboxusercontent.com/..EXAMPLE-CREDENTIALS"
/** A simple endpoint method that takes a name and says Hi back */
@ApiMethod(name = "sayHi")
public MyBean sayHi(@Named("name") String name) {
MyBean mModelClassObject = null;
String text = "";
try {
String line = "";
StringBuilder builder = new StringBuilder();
URL url = new URL("https://dl.dropboxusercontent.com/..EXAMPLE-CREDENTIALS");
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
while ((line = reader.readLine()) != null) {
// ...
builder.append(line);
}
reader.close();
text = builder.toString();
} catch (MalformedURLException e) {
// ...
} catch (IOException e) {
// ...
}
InputStream stream = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
FirebaseOptions options = null;
options = new FirebaseOptions.Builder()
.setServiceAccount(stream)
.setDatabaseUrl("https://[PROJECT-ID].firebaseio.com/")
.build();
FirebaseApp.initializeApp(options);
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
final TaskCompletionSource<MyBean> tcs = new TaskCompletionSource<>();
Task<MyBean> tcsTask = tcs.getTask();
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
MyBean result = dataSnapshot.getValue(MyBean.class);
if(result != null){
tcs.setResult(result);
}
}
@Override
public void onCancelled(DatabaseError databaseError){
//handle error
}
});
try {
mModelClassObject = Tasks.await(tcsTask);
}catch(ExecutionException e){
//handle exception
}catch (InterruptedException e){
//handle exception
}
return mModelClassObject;
}
本地方式
另一种方法是采用上面的版本并跳过类似 dropbox 的东西
/** A simple endpoint method that takes a name and says Hi back */
@ApiMethod(name = "sayHi")
public MyBean sayHi(@Named("name") String name) {
MyBean mModelClassObject = null;
String text = "JUST PASTE YOUR JSON CONTENTS HERE";
InputStream stream = new ByteArrayInputStream(text.getBytes(StandardCharsets.UTF_8));
FirebaseOptions options = null;
options = new FirebaseOptions.Builder()
.setServiceAccount(stream)
.setDatabaseUrl("https://[PROJECT-ID].firebaseio.com/")
.build();
FirebaseApp.initializeApp(options);
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
final TaskCompletionSource<MyBean> tcs = new TaskCompletionSource<>();
Task<MyBean> tcsTask = tcs.getTask();
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
MyBean result = dataSnapshot.getValue(MyBean.class);
if(result != null){
tcs.setResult(result);
}
}
@Override
public void onCancelled(DatabaseError databaseError){
//handle error
}
});
try {
mModelClassObject = Tasks.await(tcsTask);
}catch(ExecutionException e){
//handle exception
}catch (InterruptedException e){
//handle exception
}
return mModelClassObject;
}
我不知道这是否符合最佳做法,但我的项目现在正在运行。
我还包含了用于获取信息的 firebase 代码。查看我最近询问的关于读写 firebase 的
编辑
清理版本不会抛出错误
public class MyEndpoint {
private FirebaseOptions options;
private DatabaseReference ref;
private String serviceAccountJSON = "i took mine out for security reasons";
// create firebase instance if need be
private void connectToFirebase(){
if (options == null) {
options = null;
options = new FirebaseOptions.Builder()
.setServiceAccount(new ByteArrayInputStream(serviceAccountJSON.getBytes(StandardCharsets.UTF_8)))
.setDatabaseUrl("https://[PROJECT-ID].firebaseio.com/")
.build();
FirebaseApp.initializeApp(options);
}
if(ref == null) {
ref = FirebaseDatabase.getInstance().getReference();
}
}
/** A simple endpoint method that takes a name and says Hi back */
@ApiMethod(name = "sayHi")
public MyBean sayHi(@Named("name") String name) {
// always do this first
connectToFirebase();
MyBean mModelClassObject = null;
final TaskCompletionSource<MyBean> tcs = new TaskCompletionSource<>();
Task<MyBean> tcsTask = tcs.getTask();
// get the info
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
MyBean result = dataSnapshot.getValue(MyBean.class);
if(result != null){
tcs.setResult(result);
}
}
@Override
public void onCancelled(DatabaseError databaseError){
//handle error
}
});
// wait for it
try {
mModelClassObject = Tasks.await(tcsTask);
}catch(ExecutionException e){
//handle exception
}catch (InterruptedException e){
//handle exception
}
mModelClassObject.setData(mModelClassObject.getData() + name);
return mModelClassObject;
}
}
最后,我找到了解决方案,它写在 Google App Engine 的 APIs and references 部分下 link,我们需要在 appengine-[=16] 中添加这样的文件=] 文件在 <resource-files>
标签下,使用 <include path=""/>
属性。这样做之后它对我有用。我将包含项目凭据的 .json 文件放在 WEB-INF 目录中,然后在 <resource-files>
标记中输入其相对路径。