Reputation: 714
I have a page with a JSon script which is fired when a button is pressed. The script consume a web service. In order to be secured, the page code behind generates a script containing an object which contains a generated code. The code then is added to the page header. The web service should verify this code, but when it tries to get the header value by the key, the header does not exists (in other words, the header does not exists).
The code which generates the code and javascript object (in .cs file):
string cacheKey = User.Identity.Name + ":securityTicket";
string securityTicket = Guid.NewGuid().ToString();
Cache[cacheKey] = securityTicket;
string script = string.Format("SECURITY_TICKET = '{0}';", securityTicket);
ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "securityKey", script, true);
The script which add the header (in .aspx file)
function onInvoke(sender, args) {
args.get_webRequest().get_headers()['securityTicket'] = SECURITY_TICKET;);
}
The web service code behind (asmx.cs or something like this) HttpContext context = HttpContext.Current;
string headerTicket = context.Request.Headers["securityTicket"];
if (string.IsNullOrEmpty(headerTicket))
{
throw new SecurityException("Security ticket must be present.");
}
string cacheKey = context.User.Identity.Name + ":securityTicket";
string cacheTicket = (string)context.Cache[cacheKey];
if (string.Compare(headerTicket, cacheTicket, false) != 0)
{
throw new SecurityException("Security ticket mismatched.");
}
The problem is that the context.Request.Headers["securityTicket"] is null.
Any suggestions? Thank you!
UPDATE:
The Web service:
namespace PV
{
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService()]
public class UserService : System.Web.Services.WebService
{
[WebMethod]
public bool ChangeUserPassword(object userID, object password)
{
EnsureTicket();
return PV.WebMethods.ChangeUserPassword(userID, password);
}
private void EnsureTicket()
{
HttpContext context = HttpContext.Current;
string headerTicket = context.Request.Headers["securityTicket"];
if (string.IsNullOrEmpty(headerTicket))
{
throw new SecurityException("Security ticket must be present.");
}
string cacheKey = context.User.Identity.Name + ":securityTicket";
string cacheTicket = (string)context.Cache[cacheKey];
if (string.Compare(headerTicket, cacheTicket, false) != 0)
{
throw new SecurityException("Security ticket mismatched.");
}
}
}
}
The Page:
<script type="text/javascript" language="javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_beginRequest(beginRequest);
function beginRequest(sender, args) {
prm._scrollPosition = null;
postbackElement = args.get_postBackElement();
}
var postbackElement;
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(beginRequest);
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoaded);
function pageLoaded() {
Sys.Net.WebRequestManager.add_invokingRequest(onInvoke);
if (typeof (postbackElement) === "undefined") {
return;
}
if ((postbackElement.id).indexOf("btnSelect") !== -1) {
$("html, body").animate({ scrollTop: "300px" });
}
}
function ApplicationLoadHandler() {
// InitScript is a custom function
// registered from the User Control
if (typeof InitScript == 'function')
InitScript();
}
if (Sys && Sys.Application) {
Sys.Application.add_load(ApplicationLoadHandler);
Sys.Application.notifyScriptLoaded();
}
function pageUnload() {
Sys.Net.WebRequestManager.remove_invokingRequest(onInvoke);
}
function onInvoke(sender, args) {
args.get_webRequest().get_headers()['securityTicket'] = SECURITY_TICKET;
alert('Security ticket: ' + args.get_webRequest().get_headers()['securityTicket']);
}
</script>
<%
Response.Write(@"
<script>
function ResetPassword()
{
var password = document.getElementById(""password"").value;
var id = document.getElementById(""ctl00_ctl00_ContentPlaceHolder1_cphContent_hdnUsrID"").value;
var d = {""userID"" : id, ""password"" : password };
$.ajax
({
type: ""POST"",
url: """ + "" + @"http://localhost:2297/wwwroot/Services/UserService.asmx/ChangeUserPassword"",
data: JSON.stringify(d),
contentType: ""application/json"",
dataType: ""json"",
success: function()
{
document.getElementById(""password"").value = '';
alert('Succes');
$(""" + "#ctl00_ctl00_ContentPlaceHolder1_cphContent_pnlChangePassword" + @""").fadeOut();
$(""html, body"").animate
( {
scrollTop: $(""" + "#ctl00_ctl00_ContentPlaceHolder1_cphContent_pnlPerson" + @""").offset().top - 100
}, 1200);
},
error: function(msg)
{
if(msg === false)
{
alert('Error');
return;
}
}
})
}
function passwordChanged_Succes() {
alert('Changed');
}
function passwordChanged_Failed() {
alert('Failed');
}
</script>"); %>
The page also contains a update panel.
The page code behind:
private void GenerateSecurityTicket()
{
string cacheKey = User.Identity.Name + ":securityTicket";
string securityTicket = Guid.NewGuid().ToString();
Cache[cacheKey] = securityTicket;
string script = string.Format("SECURITY_TICKET = '{0}';", securityTicket);
ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "securityKey", script, true);
}
protected void Page_Load(object sender, EventArgs e)
{
this.GenerateSecurityTicket();
}
Upvotes: 2
Views: 549
Reputation: 714
So. My files looks like this:
Students.aspx
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="~/UserService.asmx" />
</Services>
</asp:ScriptManager>
<script type="text/javascript" language="javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_beginRequest(beginRequest);
function beginRequest(sender, args) {
prm._scrollPosition = null;
postbackElement = args.get_postBackElement();
}
var postbackElement;
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(beginRequest);
Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(pageLoaded);
function pageLoaded() {
Sys.Net.WebRequestManager.add_invokingRequest(onInvoke);
if (typeof (postbackElement) === "undefined") {
return;
}
}
function ApplicationLoadHandler() {
// InitScript is a custom function
// registered from the User Control
if (typeof InitScript == 'function')
InitScript();
}
if (Sys && Sys.Application) {
Sys.Application.add_load(ApplicationLoadHandler);
Sys.Application.notifyScriptLoaded();
}
function pageUnload() {
Sys.Net.WebRequestManager.remove_invokingRequest(onInvoke);
}
function onInvoke(sender, args) {
args.get_webRequest().get_headers()['securityTicket'] = SECURITY_TICKET;
}
</script>
<%Response.Write(@"
<script>
function rez() {
alert('Success!');
}
function error(e) {
alert(e.get_message());
return;
}
function ResetPassword()
{
var password = {the new password loaded from a textbox}
var id = {the user id}
UserService.ChangeUserPassword(id, password, rez, error);
}
</script>"); %>
UserService.asmx
<%@ WebService Language="C#" CodeBehind="~/App_Code/UserService.cs" Class="UserService" %>
UserService.cs
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService()]
public class UserService : System.Web.Services.WebService
{
public UserService()
{
}
[WebMethod]
public void ChangeUserPassword(object userID, object password)
{
EnsureTicket();
PV.WebMethods.ChangeUserPassword(userID, password);
}
private void EnsureTicket()
{
HttpContext context = HttpContext.Current;
string headerTicket = context.Request.Headers["securityTicket"];
if (string.IsNullOrEmpty(headerTicket))
throw new SecurityException("Security ticket must be present.");
string cacheKey = context.User.Identity.Name + ":securityTicket";
string cacheTicket = (string)context.Cache[cacheKey];
if (string.Compare(headerTicket, cacheTicket, false) != 0)
throw new SecurityException("Security ticket mismatched.");
}
}
And that's all. Should work (if I didn't forget to copy some code). For me works.
Upvotes: 1