2017-05-24 12 views
0

내 앱에서 웹 푸시 프로토콜과 함께 웹 푸시 알림을 사용하려고합니다. Push API를 VAPID와 함께 사용하려면 applicationServerKey이 필요합니다.Java에서 VAPID 키를 생성하여 JavaScript PushManager에 전달하십시오.

PushManager subscribe 메서드는 VAPID 키 (공개 키 만)를 매개 변수로 사용하여 구독 종료 지점과 키를 푸시하는 키를 제공합니다.

VAPID 키를 생성하려면 node.js (Google web-push 패키지)와 openssl을 사용하고 있습니다. 하지만 내 경우에는 VAPID 키가 자바 내에서 생성되어야하고 브라우저에서 구독하려면 JavaScript에 전달되어야합니다.

Java에서 아래 코드를 사용하여 VAPID 키를 생성하려고합니다. 성공적으로 키를 만들 수 있지만 생성 된 공개 키 (base64로 인코딩 된 문자열)를 전달할 때

서비스 작업자를 등록 할 수 없습니다. 예외 : DOMException가 'PushManager'에 은 '구독'실행하지 못했습니다 : 제공된 applicationServerKey는

날이 문제를 해결 도와주세요 .. 유효하지 않습니다. 아래 자바 코드입니다 :

ECNamedCurveParameterSpec parameterSpec = 
ECNamedCurveTable.getParameterSpec("prime256v1"); 
KeyPairGenerator keyPairGenerator = 
KeyPairGenerator.getInstance("ECDH", "BC"); 
keyPairGenerator.initialize(parameterSpec); 
KeyPair serverKey = keyPairGenerator.generateKeyPair(); 

PrivateKey priv = serverKey.getPrivate(); 
PublicKey pub = serverKey.getPublic();` 
System.out.println(Base64.toBase64String(pub.getEncoded())); 
+0

하이 - 어떤 행운이? 당신은 나에게 몇 가지 조언을 해주실 수 있습니까? – csharpnewbie

답변

1

MartijnDwars의 답변은 아래 링크를 참조하십시오. https://github.com/web-push-libs/webpush-java/issues/30

당신은 바이트 []에 자바 생성 한 PublicKey를 변환 Utils.savePublicKey를 사용할 수 있습니다. 이 바이트 []는 PushManager.subscribe 메소드에 전달됩니다.

Java에서 base64를 base64로 인코딩하고 JavaScript에서 base64로 인코딩하는 것이 더 편리 할 수 ​​있습니다. 예를 들어, 자바에서 키 쌍을 생성 한 후 :

KeyPair keyPair = generateKeyPair(); 
byte[] publicKey = Utils.savePublicKey((ECPublicKey) keyPair.getPublic()); 
String publicKeyBase64 = BaseEncoding.base64Url().encode(publicKey); 
System.out.println("PublicKey = " + publicKeyBase64); 
// PublicKey = BPf36QAqZNNvvnl9kkpTDerXUOt6Nm6P4x9GEvmFVFKgVyCVWy24KUTs6wLQtbV2Ug81utbNnx86_vZzXDyrl88= 

을 그리고 자바 스크립트 :

function subscribe() { 
    const publicKey = base64UrlToUint8Array('BPf36QAqZNNvvnl9kkpTDerXUOt6Nm6P4x9GEvmFVFKgVyCVWy24KUTs6wLQtbV2Ug81utbNnx86_vZzXDyrl88='); 

    navigator.serviceWorker.ready.then(function (serviceWorkerRegistration) { 
     serviceWorkerRegistration.pushManager.subscribe({ 
      userVisibleOnly: true, 
      applicationServerKey: publicKey 
     }) 
     .then(function (subscription) { 
      return sendSubscriptionToServer(subscription); 
     }) 
     .catch(function (e) { 
      if (Notification.permission === 'denied') { 
       console.warn('Permission for Notifications was denied'); 
      } else { 
       console.error('Unable to subscribe to push.', e); 
      } 
     }); 
    }); 
} 

function base64UrlToUint8Array(base64UrlData) { 
    const padding = '='.repeat((4 - base64UrlData.length % 4) % 4); 
    const base64 = (base64UrlData + padding) 
     .replace(/\-/g, '+') 
     .replace(/_/g, '/'); 

    const rawData = atob(base64); 
    const buffer = new Uint8Array(rawData.length); 

    for (let i = 0; i < rawData.length; ++i) { 
     buffer[i] = rawData.charCodeAt(i); 
    } 

    return buffer; 
} 
+2

솔루션에 대한 링크는 환영하지만, 답변이 없으면 응답이 유용하다는 점을 명심하십시오. [링크 주변에 컨텍스트 추가] (// meta.stackexchange.com/a/8259) 동료 사용자는 그것이 무엇인지 알 수 있습니다. 그리고 왜 그곳에 있는지, 그리고 목표 페이지를 사용할 수 없을 때 당신이 링크하고있는 페이지의 가장 중요한 부분을 인용하십시오. [링크 이상인 답변은 삭제 될 수 있습니다.] (// stackoverflow.com/help/deleted-answers) – Rob

+2

이 링크가 질문에 대답 할 수 있지만 여기에 답변의 핵심 부분을 포함시키고 참조 용 링크. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않게 될 수 있습니다. - [리뷰에서] (리뷰/저품절 포스트/17849093) –