如何在服务中包含私钥而不将其放在前端代码中?



我正在尝试通过从服务器上的专用终结点引入私有 API 密钥来在服务中包含私有 API 密钥。我只是不确定如何将其放入所需的服务中。

老实说,我对如何做到这一点有点迷茫。这是我下面的服务。私有 API 密钥用于将移动通知推送到移动设备的 onesignal 帐户。

编辑问题:

我现在稍微修改了代码,并使用了另一项名为KeysService的服务。然后,这将创建响应,允许我定义this.authKey值 - 这是一个字符串,因为这是我所需要的。

正如你会注意到的,getKey(( 方法现在正在构造函数和控制台上调用.log this.authKeys 正在打印我需要放入授权标头的相关字符串,该字符串位于其下方的 sendNotification(( 方法上。

import { Injectable } from '@angular/core';
import { OneSignal } from './onesignal';
import { environment } from '../environments/environments';
import { HttpClient, HttpHeaders, HttpBackend } from '@angular/common/http';
import { throwError } from 'rxjs';
import { KeysService } from './keys.service';
@Injectable({
providedIn: 'root'
})
export class OnesignalService {
authKey: string;
api_url = environment.one_signal.api_url;
private http: HttpClient;
constructor(handler: HttpBackend, private keysService: KeysService) {
this.http = new HttpClient(handler);
this.getkey();
}
getkey() {
this.keysService.getPrivateKeys()
.subscribe(
authKeys => {
this.authKey = authKeys.data[0].key;
console.log(this.authKey);
}
)
}
sendNotification(pushData: any) {
const httpOptions = {
headers: new HttpHeaders({
"Content-Type": "application/json; charset=utf-8",
"Authorization": "PRIVATE_API_KEY"
})
}
return this.http.post<OneSignal>(this.api_url, pushData, httpOptions);
}
handleError(error) {
let errorMessage = '';
if (error.error) {
errorMessage = error.error.message;
} else {
errorMessage = error;
}
return throwError(errorMessage);
}
}

如何将this.authKey引入sendNotification((方法,例如(见下文(:

sendNotification(pushData: any) {
const httpOptions = {
headers: new HttpHeaders({
"Content-Type": "application/json; charset=utf-8",
"Authorization": this.authKey
})
}
return this.http.post<OneSignal>(this.api_url, pushData, httpOptions);
}

我想我已经很接近了,但我错过了一个技巧来设置它。

您可以尝试以下方法。

  1. 当您从服务器接收私钥时(通常在用户登录后发生(,将其存储在浏览器的本地存储中或作为cookie。
  2. 在您的配置服务或类似服务中,有一个从本地存储或 cookie 读取此私钥的方法。
  3. 在所需的服务中注入配置服务以访问私钥。

此外,我建议使用为所有http请求设置此值的HttpInterceptor,而不是为每个服务中的每个调用设置Authorization标头。然后,您只需在该拦截器中注入配置服务。

编辑:

将密钥存储在服务本身中:

根据您编辑的问题,您正在调用以获取构造函数本身中的私钥。可以像存储服务中的任何其他变量一样存储密钥。并在sendNotification()方法中使用它,就像您现在使用this.authKey一样。你现在拥有的东西应该有效。

但是,如果重新加载页面,则将清除服务中的所有数据。将再次调用服务构造函数,进行另一次调用以获取私钥。

在页面重新加载时保留密钥:

如果您希望在页面重新加载时保留密钥,则可以将其存储在本地存储,会话存储或作为cookie中。

不将密钥存储在任何位置:

如果您不想将密钥存储在任何地方,并且每次调用该方法时都可以进行服务调用以获取私钥sendNotification()则可以遵循以下方法。

您可以连续进行两次调用 — 第一次调用以获取私钥,然后在第二次调用中使用从第一次调用作为响应收到的私钥作为 http 标头。

您可以使用 RxJS 中的 flatMap 来执行此操作。

sendNotification(pushData: any) {
return this.keysService.getPrivateKeys()
.flatMap(authKeys => {
const httpOptions = {
headers: new HttpHeaders({
"Content-Type": "application/json; charset=utf-8",
"Authorization": authKeys.data[0].key
})
};
return this.http.post<OneSignal>(this.api_url, pushData, httpOptions);
}
}

我已经让它工作了。我需要将字符串值传递到构造函数内的方法中。这样,可以在服务中的其他方法中找到它:

import { Injectable } from '@angular/core';
import { OneSignal } from './onesignal';
import { environment } from '../environments/environments';
import { HttpClient, HttpHeaders, HttpBackend } from '@angular/common/http';
import { throwError } from 'rxjs';
import { KeysService } from './keys.service';
@Injectable({
providedIn: 'root'
})
export class OnesignalService {
authKey: string;
api_url = environment.one_signal.api_url;
private http: HttpClient;
constructor(handler: HttpBackend, private keysService: KeysService) {
this.http = new HttpClient(handler);
this.getkey(this.authKey)
.subscribe(
authKeys => {
this.authKey = authKeys.data[0].key;
}
)
}
getkey(authKey) {
return this.keysService.getPrivateKeys();
}
sendNotification(pushData: any) {
const httpOptions = {
headers: new HttpHeaders({
"Content-Type": "application/json; charset=utf-8",
"Authorization": this.authKey
})
}
return this.http.post<OneSignal>(this.api_url, pushData, httpOptions);
}
handleError(error) {
let errorMessage = '';
if (error.error) {
errorMessage = error.error.message;
} else {
errorMessage = error;
}
return throwError(errorMessage);
}
}

现在,前端代码中没有放置PRIVATE_API_KEY,现在可从可通过用户令牌访问的专用终结点访问该值。一个信号服务使用 HttpBackend,因此对操作系统的请求不会被拦截,并将使用服务中的授权设置并使用 this.authKey 进行设置。

测试了它,它发送到所有设备。

最新更新