2013-10-30 116 views
1

我有一個C#Web應用程序項目,使用表單身份驗證進行保護。使用默認角色管理器管理各種頁面的授權工作正常。通過HTTPS的HTTP WCF服務

我最近添加了一些WCF(* .svc)服務到我使用Javascript從瀏覽器使用ASP.NET AJAX調用的項目(添加一個ScriptManager引用該服務)。這一切工作正常使用HTTP。

我現在已經向證書添加了一個HTTPS綁定到IIS,並試圖通過HTTPS使用該應用程序;然而,當他們嘗試加載js代理類(service.svc/jsdebug)時,引用該服務的頁面會拋出'401 Unauthorized'錯誤。從我收集的內容中,我需要更改web.config文件中的配置以使其正常工作,但找不到可以使其工作的任何設置。我需要它可以通過HTTP協議(enableWebScript)訪問,但通過HTTPS訪問。它還需要使用當前經過身份驗證的Forms用戶的身份。

有關配置web.config中的端點的任何一般建議也將被讚賞 - 或指向一個很好的教程的指針。由於

這是目前

<system.serviceModel> 
    <bindings> 
     <wsHttpBinding> 
     <binding name="WsHttpBindingConfig"> 
      <security mode="Transport"> 
      <transport clientCredentialType="None" /> 
      <message clientCredentialType="UserName"/> 
      </security> 
     </binding> 
     </wsHttpBinding> 
     <webHttpBinding> 
     <binding name="webHttp"> 
      <security mode="None"> 
      </security> 
     </binding> 
     <binding name="default"/> 
     </webHttpBinding> 
    </bindings> 
    <behaviors> 
     <endpointBehaviors> 
     <behavior name="webScriptEnablingBehavior"> 
      <enableWebScript/> 
     </behavior> 
     <behavior name="scorelink.groups.Risk"> 
      <enableWebScript /> 
     </behavior> 
     <behavior name="scorelink.tests.Benchmarks"> 
      <enableWebScript /> 
     </behavior> 
     <behavior name="default"> 
     </behavior> 
     </endpointBehaviors> 
     <serviceBehaviors> 
     <behavior name="DefaultBehaviours"> 
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/> 
      <serviceDebug includeExceptionDetailInFaults="true" /> 
      <serviceCredentials> 
      <userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="SqlProvider"/> 
      </serviceCredentials> 
      <serviceAuthorization principalPermissionMode="UseAspNetRoles" roleProviderName="SqlProvider" /> 
     </behavior> 
     <behavior name=""> 
      <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> 
      <serviceDebug includeExceptionDetailInFaults="false" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> 
    <services> 
     <service name="scorelink.groups.Risk"> 
     <endpoint address="" behaviorConfiguration="scorelink.groups.Risk" 
      binding="webHttpBinding" contract="scorelink.groups.Risk" /> 
     </service> 
     <service name="scorelink.tests.Benchmarks" behaviorConfiguration="DefaultBehaviours"> 
     <endpoint address="" behaviorConfiguration="scorelink.tests.Benchmarks" 
      binding="webHttpBinding" contract="scorelink.tests.Benchmarks" /> 
     </service> 
     <service name="scorelink.services.user" behaviorConfiguration="DefaultBehaviours"> 
     <endpoint address="" binding="wsHttpBinding" behaviorConfiguration="default" bindingConfiguration="WsHttpBindingConfig" contract="scorelink.services.Iuser" /> 
     <endpoint address="http" binding="webHttpBinding" behaviorConfiguration="webScriptEnablingBehavior" bindingConfiguration="webHttp" contract="scorelink.services.Iuser" /> 
     </service> 
    </services> 
    </system.serviceModel> 

我的web.config文件中的服務部分,因爲我一直如此,有很多事可能是有點混亂。目前我只關注user.svc,但一旦它正常工作,我會將配置應用於所有服務。

編輯

我我的配置更新爲一個建議,但現在收到以下錯誤:

The endpoint at 'https://localhost:44300/_assets/code/services/user.svc' does 
not have a Binding with the None MessageVersion. 
System.ServiceModel.Description.WebScriptEnablingBehavior' is only intended 
for use with WebHttpBinding or similar bindings. 

我認爲,這是因爲它是使用指定<enableWebScript />的終結點行爲。問題是如果我把它拿走,那麼服務不會生成一個JavaScript代理類,所以我不能從js中調用它。

編輯2 以下是ASP.NET爲響應EnableWebScript標誌而生成的js代理類的轉儲。它是從訪問http://uri/service.svc/jsdebug

Type.registerNamespace('scorelink.services'); 
scorelink.services.Iuser=function() { 
scorelink.services.Iuser.initializeBase(this); 
this._timeout = 0; 
this._userContext = null; 
this._succeeded = null; 
this._failed = null; 
} 
scorelink.services.Iuser.prototype={ 
_get_path:function() { 
var p = this.get_path(); 
if (p) return p; 
else return scorelink.services.Iuser._staticInstance.get_path();}, 
CreateUser:function(FirstName,LastName,Username,DateOfBirth,Roles,succeededCallback, failedCallback, userContext) { 
/// <param name="FirstName" type="String">System.String</param> 
/// <param name="LastName" type="String">System.String</param> 
/// <param name="Username" type="String">System.String</param> 
/// <param name="DateOfBirth" type="String">System.String</param> 
/// <param name="Roles" type="Array">System.String[]</param> 
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="userContext" optional="true" mayBeNull="true"></param> 
return this._invoke(this._get_path(), 'CreateUser',false,{FirstName:FirstName,LastName:LastName,Username:Username,DateOfBirth:DateOfBirth,Roles:Roles},succeededCallback,failedCallback,userContext); }, 
UpdateUser:function(username,firstName,lastName,dateOfBirth,roles,succeededCallback, failedCallback, userContext) { 
/// <param name="username" type="String">System.String</param> 
/// <param name="firstName" type="String">System.String</param> 
/// <param name="lastName" type="String">System.String</param> 
/// <param name="dateOfBirth" type="String">System.String</param> 
/// <param name="roles" type="Array">System.String[]</param> 
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="userContext" optional="true" mayBeNull="true"></param> 
return this._invoke(this._get_path(), 'UpdateUser',false,{username:username,firstName:firstName,lastName:lastName,dateOfBirth:dateOfBirth,roles:roles},succeededCallback,failedCallback,userContext); }, 
DeleteUser:function(Username,succeededCallback, failedCallback, userContext) { 
/// <param name="Username" type="String">System.String</param> 
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="userContext" optional="true" mayBeNull="true"></param> 
return this._invoke(this._get_path(), 'DeleteUser',false,{Username:Username},succeededCallback,failedCallback,userContext); }, 
GetUserDetails:function(Username,succeededCallback, failedCallback, userContext) { 
/// <param name="Username" type="String">System.String</param> 
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="userContext" optional="true" mayBeNull="true"></param> 
return this._invoke(this._get_path(), 'GetUserDetails',true,{Username:Username},succeededCallback,failedCallback,userContext); }, 
ChangePassword:function(oldPassword,newPassword,succeededCallback, failedCallback, userContext) { 
/// <param name="oldPassword" type="String">System.String</param> 
/// <param name="newPassword" type="String">System.String</param> 
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="userContext" optional="true" mayBeNull="true"></param> 
return this._invoke(this._get_path(), 'ChangePassword',false,{oldPassword:oldPassword,newPassword:newPassword},succeededCallback,failedCallback,userContext); }, 
ChangeLockoutCode:function(password,symbol1,symbol2,succeededCallback, failedCallback, userContext) { 
/// <param name="password" type="String">System.String</param> 
/// <param name="symbol1" type="Number">System.Int32</param> 
/// <param name="symbol2" type="Number">System.Int32</param> 
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="userContext" optional="true" mayBeNull="true"></param> 
return this._invoke(this._get_path(), 'ChangeLockoutCode',false,{password:password,symbol1:symbol1,symbol2:symbol2},succeededCallback,failedCallback,userContext); }} 
scorelink.services.Iuser.registerClass('scorelink.services.Iuser',Sys.Net.WebServiceProxy); 
scorelink.services.Iuser._staticInstance = new scorelink.services.Iuser(); 
scorelink.services.Iuser.set_path = function(value) { 
scorelink.services.Iuser._staticInstance.set_path(value); } 
scorelink.services.Iuser.get_path = function() { 
/// <value type="String" mayBeNull="true">The service url.</value> 
return scorelink.services.Iuser._staticInstance.get_path();} 
scorelink.services.Iuser.set_timeout = function(value) { 
scorelink.services.Iuser._staticInstance.set_timeout(value); } 
scorelink.services.Iuser.get_timeout = function() { 
/// <value type="Number">The service timeout.</value> 
return scorelink.services.Iuser._staticInstance.get_timeout(); } 
scorelink.services.Iuser.set_defaultUserContext = function(value) { 
scorelink.services.Iuser._staticInstance.set_defaultUserContext(value); } 
scorelink.services.Iuser.get_defaultUserContext = function() { 
/// <value mayBeNull="true">The service default user context.</value> 
return scorelink.services.Iuser._staticInstance.get_defaultUserContext(); } 
scorelink.services.Iuser.set_defaultSucceededCallback = function(value) { 
scorelink.services.Iuser._staticInstance.set_defaultSucceededCallback(value); } 
scorelink.services.Iuser.get_defaultSucceededCallback = function() { 
/// <value type="Function" mayBeNull="true">The service default succeeded callback.</value> 
return scorelink.services.Iuser._staticInstance.get_defaultSucceededCallback(); } 
scorelink.services.Iuser.set_defaultFailedCallback = function(value) { 
scorelink.services.Iuser._staticInstance.set_defaultFailedCallback(value); } 
scorelink.services.Iuser.get_defaultFailedCallback = function() { 
/// <value type="Function" mayBeNull="true">The service default failed callback.</value> 
return scorelink.services.Iuser._staticInstance.get_defaultFailedCallback(); } 
scorelink.services.Iuser.set_enableJsonp = function(value) { scorelink.services.Iuser._staticInstance.set_enableJsonp(value); } 
scorelink.services.Iuser.get_enableJsonp = function() { 
/// <value type="Boolean">Specifies whether the service supports JSONP for cross domain calling.</value> 
return scorelink.services.Iuser._staticInstance.get_enableJsonp(); } 
scorelink.services.Iuser.set_jsonpCallbackParameter = function(value) { scorelink.services.Iuser._staticInstance.set_jsonpCallbackParameter(value); } 
scorelink.services.Iuser.get_jsonpCallbackParameter = function() { 
/// <value type="String">Specifies the parameter name that contains the callback function name for a JSONP request.</value> 
return scorelink.services.Iuser._staticInstance.get_jsonpCallbackParameter(); } 
scorelink.services.Iuser.set_path("http://localhost:5584/_assets/code/services/user.svc"); 
scorelink.services.Iuser.CreateUser= function(FirstName,LastName,Username,DateOfBirth,Roles,onSuccess,onFailed,userContext) { 
/// <param name="FirstName" type="String">System.String</param> 
/// <param name="LastName" type="String">System.String</param> 
/// <param name="Username" type="String">System.String</param> 
/// <param name="DateOfBirth" type="String">System.String</param> 
/// <param name="Roles" type="Array">System.String[]</param> 
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="userContext" optional="true" mayBeNull="true"></param> 
scorelink.services.Iuser._staticInstance.CreateUser(FirstName,LastName,Username,DateOfBirth,Roles,onSuccess,onFailed,userContext); } 
scorelink.services.Iuser.UpdateUser= function(username,firstName,lastName,dateOfBirth,roles,onSuccess,onFailed,userContext) { 
/// <param name="username" type="String">System.String</param> 
/// <param name="firstName" type="String">System.String</param> 
/// <param name="lastName" type="String">System.String</param> 
/// <param name="dateOfBirth" type="String">System.String</param> 
/// <param name="roles" type="Array">System.String[]</param> 
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="userContext" optional="true" mayBeNull="true"></param> 
scorelink.services.Iuser._staticInstance.UpdateUser(username,firstName,lastName,dateOfBirth,roles,onSuccess,onFailed,userContext); } 
scorelink.services.Iuser.DeleteUser= function(Username,onSuccess,onFailed,userContext) { 
/// <param name="Username" type="String">System.String</param> 
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="userContext" optional="true" mayBeNull="true"></param> 
scorelink.services.Iuser._staticInstance.DeleteUser(Username,onSuccess,onFailed,userContext); } 
scorelink.services.Iuser.GetUserDetails= function(Username,onSuccess,onFailed,userContext) { 
/// <param name="Username" type="String">System.String</param> 
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="userContext" optional="true" mayBeNull="true"></param> 
scorelink.services.Iuser._staticInstance.GetUserDetails(Username,onSuccess,onFailed,userContext); } 
scorelink.services.Iuser.ChangePassword= function(oldPassword,newPassword,onSuccess,onFailed,userContext) { 
/// <param name="oldPassword" type="String">System.String</param> 
/// <param name="newPassword" type="String">System.String</param> 
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="userContext" optional="true" mayBeNull="true"></param> 
scorelink.services.Iuser._staticInstance.ChangePassword(oldPassword,newPassword,onSuccess,onFailed,userContext); } 
scorelink.services.Iuser.ChangeLockoutCode= function(password,symbol1,symbol2,onSuccess,onFailed,userContext) { 
/// <param name="password" type="String">System.String</param> 
/// <param name="symbol1" type="Number">System.Int32</param> 
/// <param name="symbol2" type="Number">System.Int32</param> 
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param> 
/// <param name="userContext" optional="true" mayBeNull="true"></param> 
scorelink.services.Iuser._staticInstance.ChangeLockoutCode(password,symbol1,symbol2,onSuccess,onFailed,userContext); } 
var gtc = Sys.Net.WebServiceProxy._generateTypedConstructor; 
if (typeof(scorelink.services.UserDetails) === 'undefined') { 
scorelink.services.UserDetails=gtc("UserDetails:http://schemas.datacontract.org/2004/07/scorelink.services"); 
scorelink.services.UserDetails.registerClass('scorelink.services.UserDetails'); 
} 

回答

0

我認爲有,你需要確認幾件事情:

  • 你有自簽名證書。
  • 您需要檢查SSL。
  • 你有編輯綁定 - >類型是Https - >端口是443(默認 端口)。
  • 安全模式。
  • endpoint address =「mex」binding =「mexHttpsBinding」contract =「IMetadataExchange」
  • Page.aspx.cs中您訪問服務的一些自定義代碼。
+0

(1)該網站根據自簽名認證與本地機器上安裝的公鑰一起吃飯。 (2)我沒有要求檢查SSL,因爲我希望通過HTTP和HTTPS訪問它。 (3)該網站使用自簽名證書綁定到:80和:443。 (4)不確定'安全模式'是什麼 - 你的意思是表單身份驗證? (5)我已經看到了一些對mex綁定的引用,但它不會生成js代理類。 (6)通過代理類訪問服務的代碼是javascript。 – Katstevens

+0

我的意思是安全模式是傳輸,消息等(根據需要)使用消息&clientcredentialtype =用戶名。你正在使用哪種綁定?你可以把你的JS代理類? –

+0

請參閱關於代理人的最後修訂。謝謝 – Katstevens

0

基於對所提供信息的簡要回顧,配置文件似乎沒有正確定義安全性。例如,下面的代碼片段:

<binding name="WsHttpBindingConfig"> 
     <security mode="Transport"> 
     <transport clientCredentialType="None" /> 
     <message clientCredentialType="UserName"/> 
     </security> 

...可能應該是這樣的:

<wsHttpBinding> 
     <binding name=" WsHttpBindingConfig"> 
      <security mode="TransportWithMessageCredential"> 
       <message clientCredentialType="UserName"/> 
      </security> 

以下鏈接提供了良好的背景資料:
http://msdn.microsoft.com/en-us/library/ff648840.aspx
http://www.codeproject.com/Articles/59927/WCF-Service-over-HTTPS-with-custom-username-and-pa

問候,

+0

我已經閱讀了這兩個鏈接,他們很有趣,但並不完全解決我的問題。第一個鏈接(MSDN atricle)導致我沒有獲得js代理類,因此該服務無法使用 - 該服務確實綁定到了https。第二個指南也很有趣,但也沒有結果。兩者都更注重使用指定的用戶名和密碼進行身份驗證,而不是從ASP.NET傳入已經過身份驗證的身份。思考? – Katstevens

+0

以下SO Q/A似乎解決了這個問題:http://stackoverflow.com/questions/1531100/how-can-i-pass-logged-on-user-details-from-asp-net-web-app -to-wcf-service – Seymour

+0

感謝您花時間在此。我看了一下Q/A,這是一個類似的問題,但它正在使用c#使用服務 - 我正在使用Javascript來消耗它,其中存在問題:我沒有可用的c#方法。 – Katstevens