如何在密码保护的asp.net-mvc网站上自动调用url

时间:2011-10-14 15:36:28

标签: asp.net-mvc asp.net-membership recurring-events

我有一个带有sqlserver后端的asp.net-mvc站点,我正在使用membershipprovider进行登录等。

我有一些自动化的东西,我想每天或每周运行,因为我今天可以这样做,如果我:

  1. 登录
  2. 致电网址
  3. 所以我们说URL是

    www.mysite.com/MyController/RunCleanupScript
    

    我知道有些人会建议将RunCleanupScript的代码分解为网站之外的独立脚本,但我想知道是否有自动化相当于手动登录的解决方案,然后输入此URL来调用此脚本?

7 个答案:

答案 0 :(得分:4)

Phil Haak has a post关于可能对你有用的解决方案 - 他还警告相关的危险。您可以使用此方法来安排清理任务。如果将清理代码移出控制器,则无需登录 - 永远不能从外部调用。如果您仍然需要登录并强制清理,那么将清理代码移出控制器仍然是可行的方法。您的安全操作和调度程序代码都将调用清理代码。

另一种选择可能是创建一个命中该操作的Windows服务,并将所需的凭据存储在其配置文件中。

答案 1 :(得分:2)

表单身份验证以及一些调用网页以获取cookie的脚本可能不是满足您需求的最稳定和可维护的方法。

您可以支持基本身份验证,这样可以轻松地从脚本中传递用户名和密码。有关如何在asp.net mvc中实现基本身份验证的示例,请参阅this blog post

答案 2 :(得分:2)

您可以编写一个控制台应用程序,它将执行2个HTTP请求:首先登录,然后再获取受保护资源:

using System;
using System.Collections.Specialized;
using System.Net;

public class WebClientEx: WebClient
{
    private readonly CookieContainer _cookieContainer = new CookieContainer();

    protected override WebRequest GetWebRequest(Uri address)
    {
        var request = base.GetWebRequest(address);
        ((HttpWebRequest)request).CookieContainer = _cookieContainer;
        return request;
    }
}

class Program
{
    static void Main()
    {
        using (var client = new WebClientEx())
        {
            var values = new NameValueCollection
            {
                { "username", "user" },
                { "password", "pwd" },
            };
            // Login
            client.UploadValues("http://example.com/account/logon", values);

            // Fetch the protected resource
            var result = client.DownloadString("http://example.com/home/foo");
            Console.WriteLine(result);
        }
    }
}

答案 3 :(得分:1)

此代码将登录FormsAuthentication网站,然后使用AUTH cookie命中网站上的任何其他网址...

string appURL = "https://.../LogOn";

// UserName and Password should match the names of the inputs on your form
string strPostData = String.Format("UserName={0}&Password={1}", "login", "pass");

Cookie authCookie;
CookieContainer cookieJar = new CookieContainer();

// Prepare post to the login form
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(appURL);

req.Method = "POST";
req.ContentLength = strPostData.Length;
req.ContentType = "application/x-www-form-urlencoded";
req.CookieContainer = cookieJar;
req.AutomaticDecompression = DecompressionMethods.GZip
                             | DecompressionMethods.Deflate;

// Proxy - Optional
// req.Proxy.Credentials = CredentialCache.DefaultCredentials;

// Post to the login form.
StreamWriter swRequestWriter = new StreamWriter(req.GetRequestStream());
swRequestWriter.Write(strPostData);
swRequestWriter.Close();

// Get the response.
HttpWebResponse hwrWebResponse = (HttpWebResponse)req.GetResponse();


// Store the required AUTH cookie
authCookie = cookieJar.GetCookies(new Uri("... your cookie uri ..."))[".ASPXAUTH"];

现在,您可以使用AUTH cookie访问该网站的任何其他网址。

HttpWebRequest req = (HttpWebRequest)WebRequest.Create("... url ...");

req.CookieContainer.Add(new System.Net.Cookie(authCookie.Name,
                          authCookie.Value,
                          authCookie.Path, "localhost"));

HttpWebResponse resp = (HttpWebResponse) req.GetResponse();

答案 4 :(得分:0)

PowerShell可能是一个不错的选择。这是一个示例,演示如何将表单值发布到登录页面,然后使用响应cookie再次调用管理页面。

请注意,我从this post借用了大部分此类示例。

$LogonUrl = "http://yoursite.com/Account/LogOn"
$UserName = "AdminUser"
$Password = "pass@word1"
$AdminUrl = "http://yoursite.com/MyController/RunCleanupScript"

$cookies = New-Object System.Net.CookieContainer
$formData = "UserName=" + $UserName + "&Password=" + $Password

[net.httpWebRequest] $web1 = [net.webRequest]::create($LogonUrl)
$web1.method = "POST"
$web1.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
$web1.Headers.Add("Accept-Language: en-US")
$web1.Headers.Add("Accept-Encoding: gzip,deflate")
$web1.Headers.Add("Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7")
$web1.AllowAutoRedirect = $false
$web1.ContentType = "application/x-www-form-urlencoded"
$buffer = [text.encoding]::ascii.getbytes($formData)
$web1.ContentLength = $buffer.length
$web1.TimeOut = 50000
$web1.KeepAlive = $true
$web1.Headers.Add("Keep-Alive: 300");
$web1.CookieContainer = $CookieContainer

$reqStrm = $web1.getRequestStream()
$reqStrm.write($buffer, 0, $buffer.length)
$reqStrm.flush()
$reqStrm.close()
[net.httpWebResponse] $response = $web1.getResponse()

$respStrm = $response.getResponseStream()
$reader = new-object IO.StreamReader($respStrm)
$result = $reader.ReadToEnd()
$response.close()

$web2 = new-object net.webclient
$web2.Headers.add("Cookie", $response.Headers["Set-Cookie"])
$result = $web2.DownloadString("$AdminUrl")

Write-Output $result

这也可以轻松转换为Windows控制台应用程序。无论哪种方式,使用任务计划程序都可以轻松安排它们。

希望这有帮助。

答案 5 :(得分:0)

为什么不试试WatiNSelenium?您可以非常轻松地设置登录步骤,然后测试其他RunCleanupScript页面是否正常工作。

WatiN的主页示例:

[Test] 
public void SearchForWatiNOnGoogle()
{
  using (var browser = new IE("http://www.google.com"))
  {
    browser.TextField(Find.ByName("q")).TypeText("WatiN");
    browser.Button(Find.ByName("btnG")).Click();

    Assert.IsTrue(browser.ContainsText("WatiN"));
  }
}

然后你可以有类似的东西:

[Test] 
public void TestRunCleanupScript()
{
  using (var browser = new IE("www.mysite.com/MyController/RunCleanupScript"))
  {
    DoLogin(browser)
    //navigate to cleanupscript page      
    //your assert
  }
}

public void DoLogin(browser)
{
  //navigate to login
  //type username and password and hit button
}

答案 6 :(得分:0)

我目前正在生产环境中这样做。在我的情况下,解决方案是不费脑子的,因为已经安装了MADAM,以便允许普通的RSS阅读器安全地访问网站上的RSS源。

这样做的诀窍是为您想要使用任何外部进程自动调用的页面启用基本身份验证,这将为您提供多种自动访问站点的方法;例如,这个VBScript文件调用维护URL并检查服务器的响应是否正好SUCCESS

Option Explicit

Dim result
result = PerformMaintenance("http://www.mysite.com/MyController/RunCleanupScript")
WScript.Quit(result)

Function PerformMaintenance(URL)

  Dim objRequest

  Set objRequest = CreateObject("Microsoft.XmlHttp")

  'I use a POST request because strictly speaking a GET shouldn't change anything on the server.
  objRequest.open "POST", URL, false, "LimitedDaemonUser", "SecretDaemonPassword"
  objRequest.Send

  if (objRequest.ResponseText = "SUCCESS") Then
    PerformMaintenance = 0
  Else
    PerformMaintenance = 1
  End If

  set objRequest = Nothing

End Function

基本身份验证很容易实现。只需在项目中加入MADAM,然后在Web.config中对其进行配置。

如果使用标准MembershipProvider,添加这些Web.config节/参数(IIS6)应该可以使您的示例请求正常工作。您只需将MyNamespace.MembershipUserSecurityAuthority更改为对实际课程的引用。 MembershipUserSecurityAuthority的源代码包含在MADAM的演示Web应用程序的App_Code文件夹中。

<configuration>
<configSections>
    <sectionGroup name="madam">
      <section name="userSecurityAuthority" type="System.Configuration.SingleTagSectionHandler, System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      <section name="formsAuthenticationDisposition" type="Madam.FormsAuthenticationDispositionSectionHandler, Madam" />
    </sectionGroup>
</configSections>
  <madam>
    <userSecurityAuthority realm="MyRealm" provider="MyNamespace.MembershipUserSecurityAuthority, MyNamespace" />
    <formsAuthenticationDisposition>
      <discriminators all="false">
        <discriminator inputExpression="Request.AppRelativeCurrentExecutionFilePath" pattern="~/MyController/RunCleanupScript$" type="Madam.RegexDiscriminator, Madam" />
        </discriminators>
    </formsAuthenticationDisposition>
  </madam>
  <system.web>
    <httpModules>
      <add name="FormsAuthenticationDisposition" type="Madam.FormsAuthenticationDispositionModule, Madam" />
      <add name="AuthenticationModule" type="Madam.BasicAuthenticationModule, Madam" />
    </httpModules>
  </system.web>
</configuration>