[英]Firebase Service Account Credentials Json Read permission denied
I downloaded my service account credential json file from Firebase console placed it earlier in the main directory of GAE endpoint project when I run my backed locally it gives Security exception. 我从Firebase控制台下载我的服务帐户凭据json文件时,在本地运行我的服务帐户凭据json文件时,将其更早放置在GAE端点项目的主目录中,它提供了安全性例外。
java.security.AccessControlException: access denied ("java.io.FilePermission" "\src\main\secret.json" "read")
I tried placing the .json file under the src directory also but no help. 我也尝试将.json文件放在src目录下,但没有帮助。
您应该将json文件放在src/main/resources
I found a couple ways to approach this. 我找到了几种解决方法。 First is by getting it from a file over an internet stream. 首先是通过互联网流从文件中获取它。 The other is locally. 另一个在本地。
INTERNET WAY 互联网方式
My first method involved storing the file on my public dropbox folder. 我的第一种方法涉及将文件存储在公共的保管箱文件夹中。 I got the shareable link (make sure it ends in .json
) and pasted it in the string example "https://dl.dropboxusercontent.com/..EXAMPLE-CREDENTIALS"
我得到了可共享的链接(确保它以.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;
}
LOCAL WAY 本地方式
The other way is taking the version above and skipping something like dropbox 另一种方法是采用上述版本,并跳过类似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;
}
I don't know if this follows best practice but my project is working now. 我不知道这是否遵循最佳做法,但是我的项目现在正在运行。 I also included firebase's code for getting info. 我还包括用于获取信息的firebase代码。 check out this answer to a question i asked recently on reading and writing to firebase. 查看这个答案,这是我最近在读写Firebase时提出的一个问题 。
EDIT 编辑
cleaned up version which doesnt throw errors 清理不会抛出错误的版本
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;
}
}
Finally, I found the solution, Its written under the APIs and references section of Google App Engine in this link , that we need to add such files in the appengine-web.xml file under the <resource-files>
tag, using <include path=""/>
property. 最后,在此链接中 ,我找到了解决方案(该解决方案写在Google App Engine的API和参考部分下),我们需要使用<include path=""/>
将此类文件添加到appengine-web.xml文件中的<resource-files>
标记下。 <include path=""/>
属性。 After doing so its works for me. 这样做后对我有用。 I placed the .json file containing project credentials in the WEB-INF directory and then entered its relative path in <resource-files>
tag. 我将包含项目凭证的.json文件放在WEB-INF目录中,然后在<resource-files>
标记中输入其相对路径。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.