C# 在两个 Web 应用程序之间验证 Web 服务时出现问题

标签 c# .net asp.net asp.net-mvc web-services

我正在开发一个在公司中央运行的网络应用程序。此 Web 应用程序需要调用属于第二个 Web 应用程序的服务。

在中央网络应用程序中我有这段代码;

var clientUri = "http://website.localhost/Services/Info.svc/account";
var uri = new Uri(clientUri);
var networkCredentials = new NetworkCredential(_configuration.ServiceUserName, _configuration.ServicePassword);
var httpClient = new HttpClient();

httpClient.DefaultHeaders.Authorization = Credential.CreateBasic(_configuration.ServiceUserName,                                                                                   _configuration.ServicePassword);
httpClient.TransportSettings.PreAuthenticate = true;

HttpResponseMessage respone = httpClient.Get(uri);
HttpContent content = respone.Content;

在另一个应用程序(Info.svc)的网络服务中,我在服务的构造函数中有以下代码。

var validator = new UserNamePasswordValidator();
var cred = System.Net.CredentialCache.DefaultCredentials; //this one is empty, maybe a solution?
validator.Validate("Username", "Password");

if (!HttpContext.Current.User.Identity.IsAuthenticated)
{
//This throws a 401 unauthorize, which is shown as a 500 error in the central application
throw new WebProtocolException(HttpStatusCode.Unauthorized, "You must be authorized to perform this action.", null);
}
else
{
_userIsAbleToUseService = true;
}

我想使用从其他网络服务发送过来的网络凭据,而不是验证函数中的用户名和密码,这可以实现吗?如何?欢迎任何其他建议!我现在可以在验证函数中对密码进行硬编码,但这不是我想要的。

--更新-- 这是中央应用程序的 web.config 中的配置

<authorization>
            <allow roles="administrators"/>
            <deny roles="datareaders"/>
            <deny users="?"/>
        </authorization>

<authentication mode="Forms">
            <forms loginUrl="~/Logon/Logon" timeout="2880"/>
        </authentication>
        <membership>
            <providers>
                <clear/>
                <add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" applicationName="CentralApplication"/>
            </providers>
        </membership>

这部分用于第二个 web 应用程序中的 web.config

<authentication mode="Forms">
      <forms name="AllPages" loginUrl="~/Logon/" timeout="360" enableCrossAppRedirects="false" />
    </authentication>
    <authorization>
      <!-- NOTE: See Web.config under Private folder for specifics on secure pages. -->
      <deny users="?" />
    </authorization>

<membership defaultProvider="NHMembershipProvider">
      <providers>
        <clear />
        <add name="NHMembershipProvider" applicationName="Website" type="Website.Security.Authentication.Membership.CmsMembershipProvider" description="Stores and retrieves membership data from SQL server using Nhibernate" connectionStringName="NHibernate" enablePasswordRetrieval="true" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="true" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" />
      </providers>
    </membership>
    <roleManager enabled="true" defaultProvider="NHRoleProvider">
      <providers>
        <clear />
        <add name="NHRoleProvider" applicationName="Website" type="Website.Security.Authentication.Membership.CmsRoleProvider" />
      </providers>
    </roleManager>

我已经使用成员(member)提供程序登录到中央应用程序,我正在尝试使用一个简单的超链接从那里调用网络服务(只是现在)。在中央管理员中调用的 web 服务收集一些数据并将其发送到第二个应用程序的 web 服务的 url。这两个应用程序都是 Web 应用程序(包含 Web 服务),因此身份验证模式设置为 Forms。

最佳答案

我花了将近 2 天的时间,但现在一切都如我所愿。我找到了 WcfRestContrib这使我可以通过稍微修改我的 webconfig 并使用此类中的一些属性来对服务实现身份验证。我使用服务和控制台应用程序构建了一个快速测试应用程序,并且身份验证有效。

我将以下部分添加到我的 web.config 中;

<system.serviceModel>
    <extensions>
      <behaviorExtensions>
        <add name="webAuthentication" type="WcfRestContrib.ServiceModel.Configuration.WebAuthentication.ConfigurationBehaviorElement, WcfRestContrib, Version=1.0.6.107, Culture=neutral, PublicKeyToken=89183999a8dc93b5"/>
        <add name="errorHandler" type="WcfRestContrib.ServiceModel.Configuration.ErrorHandler.BehaviorElement, WcfRestContrib, Version=1.0.6.107, Culture=neutral, PublicKeyToken=89183999a8dc93b5"/>
        <add name="webErrorHandler" type="WcfRestContrib.ServiceModel.Configuration.WebErrorHandler.ConfigurationBehaviorElement, WcfRestContrib, Version=1.0.6.107, Culture=neutral, PublicKeyToken=89183999a8dc93b5"/>
      </behaviorExtensions>
    </extensions>
    <behaviors>
      <serviceBehaviors>
        <behavior name="Rest">
          <webAuthentication requireSecureTransport="false" authenticationHandlerType="WcfRestContrib.ServiceModel.Dispatcher.WebBasicAuthenticationHandler, WcfRestContrib" usernamePasswordValidatorType="CMS.Backend.Services.SecurityValidator, CMS.Backend" source="CMS.Backend"/>
          <!--<webAuthentication requireSecureTransport="false" authenticationHandlerType="CMS.Backend.Services.WebBasicAuthenticationHandler, CMS.Backend" usernamePasswordValidatorType="CMS.Backend.Services.SecurityValidator, Website.Backend" source="CMS.Backend"/>-->
          <errorHandler errorHandlerType="WcfRestContrib.ServiceModel.Web.WebErrorHandler, WcfRestContrib"/>
          <webErrorHandler returnRawException="true" logHandlerType="Website.Backend.Services.LogHandler, Website.Backend" unhandledErrorMessage="An error has occured processing your request. Please contact technical support for further assistance."/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
  </system.serviceModel>

之后我修改了我的服务界面,看起来像这样;

[ServiceContract]
public interface ICmsInfo
{
    [OperationContract]
    [OperationAuthentication]
    [WebInvoke(UriTemplate = "account", Method = "GET")]
    AccountDTO GetAccountInfo();

我采取的最后一步是向服务本身添加 2 个属性;

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceConfiguration("Rest", true)]
public class Cmsinfo : ICmsInfo
{
//foo
}

WcfRestContrib 通过添加此身份验证技术帮了我很多,而且效果很好。我只需要确保我也使用了授权 header 。

在此之后,我在使用表单例份验证的网络应用程序中对网络服务进行身份验证时遇到了问题。此问题在另一个 topic 中指定.

关于C# 在两个 Web 应用程序之间验证 Web 服务时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3812625/

相关文章:

c# - 随着时间的推移,DispatcherTimer 会占用 CPU,导致 WPF 视觉对象无法正确呈现

c# - XAML 中的动画按钮背景颜色

.net - 我将如何正确使用 SecurityPermission 属性?

c# - 使用 LINQ 连接两个表

php - 正在尝试学习 Drupal 和 PHP 的 ASP.NET 开发人员

asp.net - UrlRewriting 在服务器上不起作用,但在本地主机上它在 asp.net 上工作正常?

C# Web 服务客户端转换错误

c# - 在白色中按类查找桌面窗口

c# 如何将文本文件的行分成两等份,并在两个不同的列表框中显示

c# - .Net Standard 对 Nuget 包的依赖