通过Python注册服务工作者时,serverApplicationKey无效
在进行服务工作者订阅时,我不断收到此错误“未经处理的拒绝(InvalidAccessError):未能对“PushManager”执行“订阅”:提供的applicationServerKey无效”。我不知道是什么导致了这个问题。我正在尝试使用Flask和React从服务器向客户端发送推送通知。我不知道这些密钥是否错误,不在服务器上注册这些乏味的密钥,或者其他什么。有人能帮我吗通过Python注册服务工作者时,serverApplicationKey无效,python,reactjs,flask,push-notification,service-worker,Python,Reactjs,Flask,Push Notification,Service Worker,在进行服务工作者订阅时,我不断收到此错误“未经处理的拒绝(InvalidAccessError):未能对“PushManager”执行“订阅”:提供的applicationServerKey无效”。我不知道是什么导致了这个问题。我正在尝试使用Flask和React从服务器向客户端发送推送通知。我不知道这些密钥是否错误,不在服务器上注册这些乏味的密钥,或者其他什么。有人能帮我吗 routes.py 提醒列表.jsx import React,{useState,useRef}来自“React”
routes.py
提醒列表.jsx
import React,{useState,useRef}来自“React”;
从“react bootstrap”导入{Form,Button,Popover,OverlyTrigger};
从“@fortawesome/react fontawesome”导入{FontAwesomeIcon}
从“@fortawesome/free solid svg icons”导入{faInfoCircle}
功能提醒列表(道具){
const[isChecked,setChecked]=使用状态(false);
const[changeInput,setChangeInput]=useState(props.text_值);
常量[storeFormData,setFormData]=useState({
提醒文字:“,
提醒日期:“,
提醒时间:“,
启用移动通知:false,
enableDesktopNotification:false,
})
const publicKey=“MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0GpiI5nprbMjvyXkWgCP43XZDBmuECPl4E/w3f7yJL+kuPEFmbYT75q/mbrmPRimlEfSjPlKGCShPVWjF6Pt9A=”
常数头={
“内容类型”:“应用程序/json”,
“授权”:props.token,
}
功能检查(e){
const id_to_be_deleted=e.target.attributes.getNamedItem(“唯一密钥”).value;
如果(!已检查){
setChecked(true);
道具添加(已选中,id将被删除);
}
否则{
setChecked(假);
道具添加(已选中,id将被删除)
}
}
函数设置更改(e){
setChangeInput(如目标值);
道具。本地存储(e);
storeFormData.rementerText=e.target.value
}
函数urlB64ToUint8Array(base64String){
常量填充='='.repeat((4-base64String.length%4)%4);
常量base64=(base64String+填充)
.替换(/\-/g,“+”)
.替换(/_/g,“/”);
const rawData=window.atob(base64);
const outputArray=新的Uint8Array(rawData.length);
for(设i=0;ires.json())。然后(res=>{
//console.log(“设置了本地存储”)
console.log(res.message);
通知()
})
异步函数notify(){
if(导航器中的“serviceWorker”和窗口中的“PushManager”){
navigator.serviceWorker.register(“/sw.js”)。然后(serviceWorkerRegistration=>{
日志('服务工作人员已注册');
log({serviceWorkerRegistration});
}).catch(错误=>{
console.log('注册服务工作人员时出错');
console.log(错误);
});
}否则{
log('浏览器不支持服务人员或推送消息');
返回;
}
const result=等待通知。requestPermission();
console.log(“权限”+结果)
如果(结果==‘拒绝’){
log('用户明确拒绝了权限请求');
返回;
}
如果(结果==‘已授予’){
log('用户接受了权限请求');
const registration=wait navigator.serviceWorker.getRegistration();
const subscribed=wait registration.pushManager.getSubscription();
如有(已签署){
log('用户已订阅');
返回;
}
const subscription=wait registration.pushManager.subscripte({
userVisibleOnly:true,
applicationServerKey:urlB64ToUint8Array(公钥)
});
取回(“http://127.0.0.1:5000/notification", {
方法:“张贴”,
标题:标题,
正文:JSON.stringify({“subscription”:subscription})
})
}
}
}
报税表(
e、 target.checked=isChecked}onClick={e=>check(e)}checked={props.checked}id=“check item”type=“checkbox”aria label=“以下文本输入的复选框”/>
setChange(e)}value={changeInput}class=“表单控制”rows=“1”name=“提醒文本”>
storeFormData.rementerDate=e.target.value}>
storeFormData.rementertime=e.target.value}>
启用移动
storeFormData.enableDesktopNotification=!storeFormData.enableDesktopNotification}
>
启用桌面
提交
}>
from database.models import User, Reminder
from database import app, request, bcrypt, db
import json
from flask_login import login_user, logout_user, current_user, login_required
from flask import jsonify
import sys
import jwt
from functools import wraps
import datetime
import datetime
import time
from database import modules
import base64
VAPID_PUBLIC_KEY = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0GpiI5nprbMjvyXkWgCP43XZDBmuECPl4E/w3f7yJL+kuPEFmbYT75q/mbrmPRimlEfSjPlKGCShPVWjF6Pt9A=="
VAPID_PRIVATE_KEY = "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgswSiYtHbjUBg4CHBpBE9vTx6CwCRFlvgQRR5hpjYnZ6hRANCAATQamIjmemtsyO/JeRaAI/jddkMGa4QI+XgT/Dd/vIkv6S48QWZthPvmr+ZuuY9GKaUR9KM+UoYJKE9VaMXo+30"
@app.route("/register", methods= ['POST', 'GET'])
def registerForm():
if request.method == 'POST':
name = request.form["personName"]
number = request.form["phoneNumber"]
email = request.form["personEmail"]
password = request.form["password"]
confirmPassword = request.form["confirmPassword"]
duplicateEmail = User.query.filter_by(email=email).first()
if password != confirmPassword:
return json.dumps({"passwordError": "Passwords Do Not Match! "}), 403
if duplicateEmail is not None:
return json.dumps({"duplicateEmailError": "E-mail Already Exists! Please sign in."}), 409
pw_hash = bcrypt.generate_password_hash(password).decode('utf-8')
user = User(name = name, email = email, password = pw_hash, number = number)
db.session.add(user)
db.session.commit()
return json.dumps({"message": "Successfully Registered"}),200
@app.route("/login", methods = ['POST', 'GET'])
def logInForm():
if request.method == 'POST':
email = request.form['personEmail']
password = request.form['password']
getPerson = User.query.filter_by(email=email).first()
if getPerson != None:
hash_pass = getPerson.password
if getPerson and bcrypt.check_password_hash(hash_pass, password):
login_user(getPerson)
token = jwt.encode({'public_id': getPerson.id, 'exp': datetime.datetime.utcnow() + datetime.timedelta(days=365)}, app.config['SECRET_KEY'] )
return jsonify({'token':token.decode('UTF-8')})
return json.dumps({"errorMessage":"E-mail Does Not Exist or Password Is Incorrect"}), 404
@app.route("/logout", methods = ['POST', 'GET'])
def logout():
return json.dumps({"logOut": True})
def token_required(f):
@wraps(f)
def decorator(*args, **kwargs):
req_data = {}
req_data['headers'] = dict(request.headers)
token = req_data['headers']['Authorization']
if token == "undefined":
return jsonify({'message': 'Token is missing.'}), 404
try:
data = jwt.decode(token, app.config['SECRET_KEY'])
current_user = User.query.filter_by(id=data['public_id']).first()
except:
return jsonify({'message': 'token is invalid'}), 401
return f(current_user, *args, **kwargs)
return decorator
@app.route("/reminders", methods =['POST', 'GET'])
@token_required
def createReminders(current_user):
if request.method == 'POST':
form = json.loads(request.data.decode('UTF-8'))
date = form['reminderDate'].split("-")
time = form['reminderTime'].split(":")
dateAndTime = datetime.datetime(int(date[0]), int(date[1]), int(date[2]), int(time[0]), int(time[1]))
text = form['reminderText']
enableMobileNotification = True if form['enableMobileNotification'] is True else False
enableDesktopNotification = True if form['enableDesktopNotification'] is True else False
appointmentDate = datetime.datetime(int(date[0]), int(date[1]), int(date[2]))
getTodayDate = datetime.datetime.today().strftime('%Y-%m-%d').split("-")
todayDate = datetime.datetime(int(getTodayDate[0]), int(getTodayDate[1]), int(getTodayDate[2]))
createReminder = Reminder(
text=text,
date = dateAndTime,
notifyMobile = enableMobileNotification,
notifyDesktop = enableDesktopNotification,
numberOfDaysUntilAppointment = modules.cal_days_diff(appointmentDate, todayDate),
person_id = current_user.id
)
db.session.add(createReminder)
db.session.commit()
return jsonify({"message": "Successfully Updated"}), 200
@app.route("/notification", methods = ['POST'])
@token_required
def setNotifications(current_user):
form = json.loads(request.data.decode('UTF-8'))
subscription = form["subscription"]
createNotif = Reminder(subscription = subscription)
db.session.add(createNotif)
db.session.commit()
message = "Hello From Server"
VAPID_CLAIMS = {
"sub": "my email"
}
try:
modules.send_web_push(subscription, message, VAPID_PRIVATE_KEY, VAPID_CLAIMS)
return jsonify({'success':1})
except Exception as e:
print("error",e)
return jsonify({'failed':str(e)})
import React, {useState, useRef} from "react";
import {Form, Button,Popover, OverlayTrigger} from "react-bootstrap";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import {faInfoCircle} from '@fortawesome/free-solid-svg-icons'
function ReminderLists(props) {
const [isChecked, setChecked] = useState(false);
const [changeInput, setChangeInput] = useState(props.text_value);
const [storeFormData, setFormData] = useState({
reminderText: "",
reminderDate: "",
reminderTime: "",
enableMobileNotification: false,
enableDesktopNotification:false,
})
const publicKey = "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE0GpiI5nprbMjvyXkWgCP43XZDBmuECPl4E/w3f7yJL+kuPEFmbYT75q/mbrmPRimlEfSjPlKGCShPVWjF6Pt9A=="
const header = {
'Content-Type': 'application/json',
'Authorization': props.token,
}
function check(e) {
const id_to_be_deleted = e.target.attributes.getNamedItem("unique_Key").value;
if(!isChecked) {
setChecked(true);
props.addIds(isChecked, id_to_be_deleted);
}
else {
setChecked(false);
props.addIds(isChecked, id_to_be_deleted)
}
}
function setChange(e) {
setChangeInput(e.target.value);
props.local_storage(e);
storeFormData.reminderText=e.target.value
}
function urlB64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
function handleSubmit(e) {
console.log("Token in reminder list " + props.token)
e.preventDefault();
fetch('http://127.0.0.1:5000/reminders', {
method: 'POST',
headers:header,
body: JSON.stringify(storeFormData)
}).then(res=>res.json()).then(res=> {
// console.log("Local storage is set")
console.log(res.message);
notify()
})
async function notify() {
if ('serviceWorker' in navigator && 'PushManager' in window) {
navigator.serviceWorker.register("/sw.js").then(serviceWorkerRegistration => {
console.log('Service worker was registered.');
console.log({serviceWorkerRegistration});
}).catch(error => {
console.log('An error occurred while registering the service worker.');
console.log(error);
});
} else {
console.log('Browser does not support service workers or push messages.');
return;
}
const result = await Notification.requestPermission();
console.log("Permission " + result)
if (result === 'denied') {
console.log('The user explicitly denied the permission request.');
return;
}
if (result === 'granted') {
console.log('The user accepted the permission request.');
const registration = await navigator.serviceWorker.getRegistration();
const subscribed = await registration.pushManager.getSubscription();
if (subscribed) {
console.log('User is already subscribed.');
return;
}
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlB64ToUint8Array(publicKey)
});
fetch("http://127.0.0.1:5000/notification", {
method: "POST",
headers:header,
body: JSON.stringify({"subscription":subscription})
})
}
}
}
return (
<Form>
<fieldset>
<div className = "input-group mb-3">
<div className="input-group-prepend">
<div className="input-group-text">
<input unique_Key = {props.id} onInput = {e=> e.target.checked = isChecked} onClick={e=> check(e) } checked = {props.checked} id = "check-item" type="checkbox" aria-label="Checkbox for following text input"/>
</div>
</div>
<textarea id = {props.id} onChange = {e=>setChange(e)} value = {changeInput} class="form-control" rows="1" name = "reminderText" ></textarea>
<input type="date" id="start" name="reminderDate" onChange = {(e)=> storeFormData.reminderDate=e.target.value}></input>
<input type="time" id="appt" name="reminderTime" min="09:00" max="18:00" required onChange = {(e)=> storeFormData.reminderTime=e.target.value}></input>
<OverlayTrigger
trigger="click"
key={'bottom'}
placement={'bottom'}
overlay={
<Popover id={`popover-positioned-${'bottom'}`}>
<Popover.Title as="h3">{`Notification Settings`}</Popover.Title>
<Popover.Content>
<div>
<input type="checkbox" id= "mobile" name="enableMobileNotification" value= "mobile"
onChange = {(e)=> storeFormData.enableMobileNotification= !storeFormData.enableMobileNotification}>
</input>
<label className = "padding-left" for="mobile">Enable Mobile</label>
</div>
<div>
<input type="checkbox" id="desktop" name="enableDesktopNotification" value="desktop"
onChange = {(e)=> storeFormData.enableDesktopNotification= !storeFormData.enableDesktopNotification}
>
</input>
<label className = "padding-left" for="desktop">Enable Desktop</label>
</div>
<Button variant="primary" size="sm" type="submit" onClick = {handleSubmit}>Submit</Button>
</Popover.Content>
</Popover>
}>
<Button className = "black app-btns " id="Popover1" type="button">
<FontAwesomeIcon icon = {faInfoCircle} size = "2x" />
</Button>
</OverlayTrigger>
</div>
</fieldset>
</Form>
)
}
export {ReminderLists};