C# 发送web推送通知并收到意外响应代码:401&;403

C# 发送web推送通知并收到意外响应代码:401&;403,c#,asp.net,webforms,service-worker,web-push,C#,Asp.net,Webforms,Service Worker,Web Push,我使用web推送api在asp.net web表单中使用javascript和c#向订阅用户发送通知。 对于订阅,我使用notification.permission方法和服务工作者,当用户允许权限时,我将在数据库中保存订阅数据,包括公钥、私钥、端点、身份验证、p256dh 为了发送通知,我创建了一个服务,它从数据库中获取数据,并使用ServiceWorker将通知发送给这些用户。 问题是,当我向3000个用户发送通知时,它只成功地向700个用户发送了通知,其余用户抛出错误 收到意外响应代码:4

我使用web推送api在asp.net web表单中使用javascript和c#向订阅用户发送通知。 对于订阅,我使用notification.permission方法和服务工作者,当用户允许权限时,我将在数据库中保存订阅数据,包括公钥、私钥、端点、身份验证、p256dh

为了发送通知,我创建了一个服务,它从数据库中获取数据,并使用ServiceWorker将通知发送给这些用户。 问题是,当我向3000个用户发送通知时,它只成功地向700个用户发送了通知,其余用户抛出错误 收到意外响应代码:403 收到意外响应代码:401

我搜索了这些错误,因为它似乎是b身份验证错误,但找不到如何避免它,因为所有订阅者都使用相同的方法,但为什么大部分都失败了,很少成功

我已经在asp.net web窗体应用程序中实现了此代码

createdevice.js文件

Notification.requestPermission().then(function (status) {
    debugger;
    if (status === 'denied') {`enter code here`
        errorHandler('[Notification.requestPermission] Browser denied permissions to notification api.');
    } else if (status === 'granted') {

        console.log('[Notification.requestPermission] Initializing service worker.');
        debugger;
        initialiseServiceWorker();
        debugger;

            subscribe();




    }
});
debugger;
函数subscribe()

sw.js

self.addEventListener('push',函数(事件)

index.aspx文件:

<script src="sw1.js"></script>
<script src="js/CreateDevice.js"></script>

<input id="PushEndpoint" runat="server" />
<input id="PushP256DH" runat="server"/>
<input id="PushAuth" runat="server"/>

<form id="form1" runat="server">
<div>
<asp:Button ID="send_notification" Text="Send Notification" runat="server" OnClick="send_notification_Click"/>

     <button id="unsub">Unsub</button>
</div>
</form>

不明嫌犯
index.aspx.cs

public partial class index : System.Web.UI.Page
{
    public string FromServer;
    public static string publicKey;
    public static string privateKey;
    protected void Page_Load(object sender, EventArgs e)
    {
        var keys = VapidHelper.GenerateVapidKeys();
        FromServer = keys.PublicKey;
        publicKey = keys.PublicKey;
        privateKey = keys.PrivateKey;
        StringBuilder strScript = new StringBuilder();

        strScript.Append("<script type=\"text/javascript\">");

        strScript.Append("var applicationServerPublicKey='");

        strScript.Append(FromServer);

        strScript.Append("';");

        strScript.Append("</script>");



        ClientScriptManager script = Page.ClientScript;



        if (!script.IsClientScriptBlockRegistered(this.GetType(), "Var"))

        {

            script.RegisterClientScriptBlock(this.GetType(), "Var", strScript.ToString());

        }

    }
    [WebMethod]
    public static string saveCredentialsInDb(string endpoint, string p256dh, string auth)
    {
        var _publicKey = publicKey;
        var _privateKey = privateKey;
        var isError = false;
        string conStr = ConfigurationManager.ConnectionStrings["sqlConString"].ConnectionString;
        string query = @"INSERT INTO userCredentials (PublicKey, PrivateKey, [Endpoint], Auth, p256dh)
                        VALUES (@PublicKey, @PrivateKey, @Endpoint, @Auth, @p256dh)";

        // create connection and command
         SqlConnection cn = new SqlConnection(conStr);
            using (SqlCommand cmd = new SqlCommand(query, cn))
            {
                // define parameters and their values
                cmd.Parameters.AddWithValue("@PublicKey", _publicKey);
                cmd.Parameters.AddWithValue("@PrivateKey", _privateKey);
                cmd.Parameters.AddWithValue("@Endpoint", endpoint);
                cmd.Parameters.AddWithValue("@Auth", auth);
                cmd.Parameters.AddWithValue("@p256dh", p256dh);
                // open connection, execute INSERT, close connection
                cn.Open();
            //if (isError == false)
            //{
                cmd.ExecuteNonQuery();
            //}
                cn.Close();
            }
        //if (isError == true)
        //{
        //    return "invalid";
        //}
        //else
        //{
            return "OK";
        //}

    }
    public class Data
    {
        [JsonProperty("Title")]
        public string Title { get; set; }
        [JsonProperty("Message")]
        public string Message { get; set; }
        [JsonProperty("Image")]
        public string Image { get; set; }

    }
    public class TimeToLive
    {

        public int Num { get; set; }

    }

    protected void send_notification_Click(object sender, EventArgs e)
    {
        DataTable dt = new DataTable();
        string message = "";
        string title = "";
        byte[] image = new byte[] { };
        string publicKey1 = "";
        string privateKey1 = "";
        string endpoint = "";
        string auth = "";
        string p256dh = "";
        string base64image = "";
        List<string> listData = new List<string>();
        string conStr = ConfigurationManager.ConnectionStrings["sqlConString"].ConnectionString;
        string query = @"SELECT * from userCredentials, [Payload]";

        // create connection and command
        SqlConnection cn = new SqlConnection(conStr);
        using (SqlCommand cmd = new SqlCommand(query, cn))
        {
            // define parameters and their values

            // open connection, execute INSERT, close connection
            cn.Open();
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            // this will query your database and return the result to your datatable
            da.Fill(dt);
            cn.Close();
        }
        Data body = new Data();

        foreach (DataRow row in dt.Rows)
        {

            //message = row["Message"].ToString();
            //title = row["Title"].ToString();
            publicKey1 = row["PublicKey"].ToString();
            privateKey1 = row["PrivateKey"].ToString();
            endpoint = row["Endpoint"].ToString();
            auth = row["Auth"].ToString();
            p256dh = row["p256dh"].ToString();
            message = row["Message"].ToString();
            title = row["Title"].ToString();
            //string strfn = Convert.ToString(DateTime.Now.ToFileTime());
            //FileStream fs = new FileStream(strfn,
            //                  FileMode.CreateNew, FileAccess.Write);
            //fs.Write(Bimage, 0, Bimage.Length);
            //fs.Flush();
            //fs.Close();
            // FromFile(strfn);

            //image = "data:images/png;base64,"+ base64image;

        }
        //listData.Add(title);
        //listData.Add(message);
        body.Title = title;
        body.Message = message;
        //body.Image = base64image.ToString(); 
        var payload = JsonConvert.SerializeObject(body);

    var pushSubscription = new PushSubscription(endpoint, p256dh, auth);
            //var vapidDetails = new VapidDetails("mailto:example@example.com", publicKey1, privateKey1);
        var options = new Dictionary<string, object>();
        options["vapidDetails"] = new VapidDetails("mailto:example@example.com", publicKey1, privateKey1);
        //TimeToLive ttl = new TimeToLive();
        //ttl.Num = 3600;
        //options["TTL"] = 3600;

        var webPushClient = new WebPushClient();
        try
        {
            webPushClient.SendNotificationAsync(pushSubscription, payload, options);
        }
        catch (WebPushException ex)
        {
            throw ex;
        }


    }
}
公共部分类索引:System.Web.UI.Page
{
来自服务器的公共字符串;
公共静态字符串公钥;
公共静态字符串私钥;
受保护的无效页面加载(对象发送方、事件参数e)
{
var keys=VapidHelper.GenerateVapidKeys();
FromServer=keys.PublicKey;
publicKey=keys.publicKey;
privateKey=keys.privateKey;
StringBuilder strScript=新建StringBuilder();
strScript.Append(“”);
追加(“var applicationServerPublicKey=”);
strScript.Append(FromServer);
strScript.Append(“;”);
strScript.Append(“”);
ClientScriptManager脚本=Page.ClientScript;
如果(!script.IsClientScriptBlockRegistered(this.GetType(),“Var”))
{
script.RegisterClientScriptBlock(this.GetType(),“Var”,strScript.ToString());
}
}
[网络方法]
公共静态字符串saveCredentialsInDb(字符串端点、字符串p256dh、字符串身份验证)
{
var _publicKey=publicKey;
var _privateKey=privateKey;
var-isError=false;
string conStr=ConfigurationManager.ConnectionString[“sqlConString”].ConnectionString;
字符串查询=@“插入到用户凭据中(公钥、私钥、[Endpoint]、身份验证、p256dh)
值(@PublicKey、@PrivateKey、@Endpoint、@Auth、@p256dh)”;
//创建连接和命令
SqlConnection cn=新的SqlConnection(conStr);
使用(SqlCommand cmd=newsqlcommand(query,cn))
{
//定义参数及其值
cmd.Parameters.AddWithValue(“@PublicKey”,_PublicKey);
cmd.Parameters.AddWithValue(“@PrivateKey”,_PrivateKey);
cmd.Parameters.AddWithValue(“@Endpoint”,Endpoint);
cmd.Parameters.AddWithValue(“@Auth”,Auth);
cmd.Parameters.AddWithValue(“@p256dh”,p256dh);
//打开连接,执行插入,关闭连接
cn.Open();
//if(isError==false)
//{
cmd.ExecuteNonQuery();
//}
cn.Close();
}
//如果(isError==真)
//{
//返回“无效”;
//}
//否则
//{
返回“OK”;
//}
}
公共类数据
{
[JsonProperty(“所有权”)]
公共字符串标题{get;set;}
[JsonProperty(“消息”)]
公共字符串消息{get;set;}
[JsonProperty(“图像”)]
公共字符串图像{get;set;}
}
公共类计时生活
{
公共int Num{get;set;}
}
受保护的无效发送通知单击(对象发送者,事件参数e)
{
DataTable dt=新的DataTable();
字符串消息=”;
字符串标题=”;
字节[]图像=新字节[]{};
字符串publicKey1=“”;
字符串privateKey1=“”;
字符串端点=”;
字符串auth=“”;
字符串p256dh=“”;
字符串base64image=“”;
List listData=新列表();
string conStr=ConfigurationManager.ConnectionString[“sqlConString”].ConnectionString;
字符串查询=@“从用户凭据中选择*,[Payload]”;
//创建连接和命令
SqlConnection cn=新的SqlConnection(conStr);
使用(SqlCommand cmd=newsqlcommand(query,cn))
{
//定义参数及其值
//打开连接,执行插入,关闭连接
cn.Open();
SqlDataAdapter da=新的SqlDataAdapter(cmd);
//这将查询数据库并将结果返回到datatable
da.填充(dt);
cn.Close();
}
数据体=新数据();
foreach(数据行中的数据行)
{
//message=行[“message”]。ToString();
//title=行[“title”]。ToString();
publicKey1=行[“PublicKey”]。ToString();
privateKey1=行[“PrivateKey”].ToString();
端点=行[“端点”]。ToString();
auth=行[“auth”].ToString();
p256dh=行[“p256dh”].ToString();
message=行[“message”]。ToString();
title=行[“title”]。ToString();
//字符串strfn=Convert.ToString(DateTime.Now.ToFileTime());
//FileStream fs=新的FileStream(strfn,
//FileMode.CreateNew,FileAccess.Write);
//fs.Write(双页,0,双页,长度);
//fs.Flush();
//fs.Close();
//FromFile(strfn);
//image=“data:images/png;base64,”+base64图像;
}
//添加(标题);
//添加(消息);
生化需氧量
<script src="sw1.js"></script>
<script src="js/CreateDevice.js"></script>

<input id="PushEndpoint" runat="server" />
<input id="PushP256DH" runat="server"/>
<input id="PushAuth" runat="server"/>

<form id="form1" runat="server">
<div>
<asp:Button ID="send_notification" Text="Send Notification" runat="server" OnClick="send_notification_Click"/>

     <button id="unsub">Unsub</button>
</div>
</form>
public partial class index : System.Web.UI.Page
{
    public string FromServer;
    public static string publicKey;
    public static string privateKey;
    protected void Page_Load(object sender, EventArgs e)
    {
        var keys = VapidHelper.GenerateVapidKeys();
        FromServer = keys.PublicKey;
        publicKey = keys.PublicKey;
        privateKey = keys.PrivateKey;
        StringBuilder strScript = new StringBuilder();

        strScript.Append("<script type=\"text/javascript\">");

        strScript.Append("var applicationServerPublicKey='");

        strScript.Append(FromServer);

        strScript.Append("';");

        strScript.Append("</script>");



        ClientScriptManager script = Page.ClientScript;



        if (!script.IsClientScriptBlockRegistered(this.GetType(), "Var"))

        {

            script.RegisterClientScriptBlock(this.GetType(), "Var", strScript.ToString());

        }

    }
    [WebMethod]
    public static string saveCredentialsInDb(string endpoint, string p256dh, string auth)
    {
        var _publicKey = publicKey;
        var _privateKey = privateKey;
        var isError = false;
        string conStr = ConfigurationManager.ConnectionStrings["sqlConString"].ConnectionString;
        string query = @"INSERT INTO userCredentials (PublicKey, PrivateKey, [Endpoint], Auth, p256dh)
                        VALUES (@PublicKey, @PrivateKey, @Endpoint, @Auth, @p256dh)";

        // create connection and command
         SqlConnection cn = new SqlConnection(conStr);
            using (SqlCommand cmd = new SqlCommand(query, cn))
            {
                // define parameters and their values
                cmd.Parameters.AddWithValue("@PublicKey", _publicKey);
                cmd.Parameters.AddWithValue("@PrivateKey", _privateKey);
                cmd.Parameters.AddWithValue("@Endpoint", endpoint);
                cmd.Parameters.AddWithValue("@Auth", auth);
                cmd.Parameters.AddWithValue("@p256dh", p256dh);
                // open connection, execute INSERT, close connection
                cn.Open();
            //if (isError == false)
            //{
                cmd.ExecuteNonQuery();
            //}
                cn.Close();
            }
        //if (isError == true)
        //{
        //    return "invalid";
        //}
        //else
        //{
            return "OK";
        //}

    }
    public class Data
    {
        [JsonProperty("Title")]
        public string Title { get; set; }
        [JsonProperty("Message")]
        public string Message { get; set; }
        [JsonProperty("Image")]
        public string Image { get; set; }

    }
    public class TimeToLive
    {

        public int Num { get; set; }

    }

    protected void send_notification_Click(object sender, EventArgs e)
    {
        DataTable dt = new DataTable();
        string message = "";
        string title = "";
        byte[] image = new byte[] { };
        string publicKey1 = "";
        string privateKey1 = "";
        string endpoint = "";
        string auth = "";
        string p256dh = "";
        string base64image = "";
        List<string> listData = new List<string>();
        string conStr = ConfigurationManager.ConnectionStrings["sqlConString"].ConnectionString;
        string query = @"SELECT * from userCredentials, [Payload]";

        // create connection and command
        SqlConnection cn = new SqlConnection(conStr);
        using (SqlCommand cmd = new SqlCommand(query, cn))
        {
            // define parameters and their values

            // open connection, execute INSERT, close connection
            cn.Open();
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            // this will query your database and return the result to your datatable
            da.Fill(dt);
            cn.Close();
        }
        Data body = new Data();

        foreach (DataRow row in dt.Rows)
        {

            //message = row["Message"].ToString();
            //title = row["Title"].ToString();
            publicKey1 = row["PublicKey"].ToString();
            privateKey1 = row["PrivateKey"].ToString();
            endpoint = row["Endpoint"].ToString();
            auth = row["Auth"].ToString();
            p256dh = row["p256dh"].ToString();
            message = row["Message"].ToString();
            title = row["Title"].ToString();
            //string strfn = Convert.ToString(DateTime.Now.ToFileTime());
            //FileStream fs = new FileStream(strfn,
            //                  FileMode.CreateNew, FileAccess.Write);
            //fs.Write(Bimage, 0, Bimage.Length);
            //fs.Flush();
            //fs.Close();
            // FromFile(strfn);

            //image = "data:images/png;base64,"+ base64image;

        }
        //listData.Add(title);
        //listData.Add(message);
        body.Title = title;
        body.Message = message;
        //body.Image = base64image.ToString(); 
        var payload = JsonConvert.SerializeObject(body);

    var pushSubscription = new PushSubscription(endpoint, p256dh, auth);
            //var vapidDetails = new VapidDetails("mailto:example@example.com", publicKey1, privateKey1);
        var options = new Dictionary<string, object>();
        options["vapidDetails"] = new VapidDetails("mailto:example@example.com", publicKey1, privateKey1);
        //TimeToLive ttl = new TimeToLive();
        //ttl.Num = 3600;
        //options["TTL"] = 3600;

        var webPushClient = new WebPushClient();
        try
        {
            webPushClient.SendNotificationAsync(pushSubscription, payload, options);
        }
        catch (WebPushException ex)
        {
            throw ex;
        }


    }
}