Avatar billede thesurfer Nybegynder
19. november 2007 - 22:11 Der er 27 kommentarer og
1 løsning

Login på webside via C#, og opretholde session/cookie

Jeg har brug for at kunne logge ind på en webside (post HTTP data fra C#), og samtidigt opretholde session/cookie.

Med det mener jeg, at jeg skal sende brugernavn og kodeord, og få en cookie retur, som man kan bruge ved næste kald, så jeg kan få adgang til de beskyttede sider (som man har adgang til, efter login).


Jeg er igang med at spille et browser-baseret spil (online), der kræver login (hvilket jeg naturligvis har). I stedet for at bruge browseren, vil jeg gerne lave en klient til spillet.


Jeg vil derfor gerne høre fra folk, der har guides/tutorials i opbygning af ligende applikationer, folk der har eksempler (med kode) på disse applikationer, osv...

Jeg foretrækker en løsning, jeg kan lære af, i stedet for en komplet applikation.
Avatar billede arne_v Ekspert
19. november 2007 - 22:15 #1
Grundliggende skal du bare lave alle kald med samme CookieContainer.

Eksempel:

using System;
using System.IO;
using System.Net;

namespace E
{
    public class MainClass
    {
        public static string GetContent(string url, CookieContainer session)
        {
            HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
            wr.CookieContainer = session;           
            string html = (new StreamReader(wr.GetResponse().GetResponseStream())).ReadToEnd();
            return html;
        }
        public static void Main(string[] args)
        {
            CookieContainer session = new CookieContainer();
            string login = GetContent("http://localhost:8080/logintest/login.jsp?username=arne&password=hemmeligt", session);
            Console.WriteLine(login);
            string other = GetContent("http://localhost:8080/logintest/other.jsp", session);
            Console.WriteLine(other);
        }
    }
}

Det var saa med 2 x GET, men (Http)WebRequest kan ogsaa lave POST.
Avatar billede thesurfer Nybegynder
19. november 2007 - 22:20 #2
Det vil jeg prøve med det samme.. :-)

Tak for det hurtige svar.
Avatar billede thesurfer Nybegynder
19. november 2007 - 23:01 #3
Det ser ikke ud til at virke..

Jeg prøvede først med method="POST" på formen, og derefter method="GET".. no go..

Der er 2 textboxe på formen, kaldet txtuser og txtpass..

Funktionen "output" tilføjer bare den medfølgende streng/parameter til en textbox..


*** Kode:

FORM:
...
using System.Net;
using System.IO;
...

    public partial class Form1 : Form
    {
        private string mypage_login = "http://localhost:4678/Website/";
        private string mypage_second = "http://localhost:4678/Website/protectedpage.aspx";
        public Form1()
        {
            InitializeComponent();
        }

        private void output(string txt)
        {
            // denne textbox (multiline med scrollbar) viser HTML koden:
            tbxRes.Text += txt + "\r\n";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            CookieContainer session = new CookieContainer();
            string login = GetContent(mypage_login, session);
            //Console.WriteLine(login);
            output(login);

            output("---------------------------------------------------------------------");

            string other = GetContent(mypage_second, session);
            //Console.WriteLine(other);
            output(other);
        }


WEB - LOGIN:

    // Beskyttelsesmekanismen bag login-formen:
    protected void Page_Load(object sender, EventArgs e)
    {
        if (Request.QueryString["action"] != null)
        {
            if (Request.QueryString["action"] == "logout")
            {
                Session["log"] = null;
                Response.Redirect("default.aspx");
            }
        }

        if (IsPostBack)
        {
            if (Request.QueryString["txtuser"] == "a" && Request.QueryString["txtpass"] == "b")
            {
                Session["log"] = true;
                Response.Redirect("protectedpage.aspx");
            }
            else
            {
                span_errormsg.InnerHtml = "Wrong username or password";
                span_errormsg.Visible = true;
            }
        }
    }


WEB - PROTECTED:

    // Her undersøges om siden må vises
    protected void Page_Load(object sender, EventArgs e)
    {
        if (Session["log"] == null) Response.Redirect("default.aspx");
    }
Avatar billede thesurfer Nybegynder
19. november 2007 - 23:05 #4
Jeg kommer lige i tanke om noget.. :-)

Jeg skal vel tilføje brugernavn og kodeord til den første url.. og jeg kan jo ikke bruge IsPostBack, når det er querystringen jeg aflæser.. :-)
Avatar billede thesurfer Nybegynder
19. november 2007 - 23:07 #5
De eneste rettelser til forrige kode:

FORM:

        // test med fejl da det skal være "a" og "b".
        private string mypage_login = "http://localhost:4678/Website/default.aspx?txtuser=a&txtpass=a";


WEB - LOGIN:

    // Beskyttelsesmekanismen bag login-formen:
    protected void Page_Load(object sender, EventArgs e)
    {
        if (Request.QueryString["action"] != null)
        {
            if (Request.QueryString["action"] == "logout")
            {
                Session["log"] = null;
                Response.Redirect("default.aspx");
            }
        }

        if (Request.QueryString["txtuser"] == "a" && Request.QueryString["txtpass"] == "b")
        {
            Session["log"] = true;
            Response.Redirect("protectedpage.aspx");
        }
        else
        {
            span_errormsg.InnerHtml = "Wrong username or password";
            span_errormsg.Visible = true;
        }
    }
Avatar billede arne_v Ekspert
19. november 2007 - 23:07 #6
Hvis login kraever POST saa skal du jo have en PostContent metode der saetter Method til
POST og sender form felter i body.
Avatar billede thesurfer Nybegynder
19. november 2007 - 23:08 #7
Hmm... Jeg har lige prøvet med:

http://localhost:4678/Website/default.aspx?txtuser=a&txtpass=b

Jeg får indholdet af protectedpage.aspx, ved begge kald..?
Avatar billede thesurfer Nybegynder
19. november 2007 - 23:13 #8
Ved at bruge URL/QueryString, kan jeg droppe formen helt, og behøver vel ikke længere spekulere i POST og PostContent, korrekt?

Så burde det virke med linket, hvilket det ikke gør:

http://localhost:4678/Website/default.aspx?txtuser=a&txtpass=b
Avatar billede arne_v Ekspert
20. november 2007 - 02:57 #9
Det er langtfra alle sider der tillader at man kan bruge både POST og GET.

Prøv med en korrekt POST.
Avatar billede arne_v Ekspert
20. november 2007 - 02:58 #10
code snippet:

        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
        req.Method = "POST";
        req.ContentType = "application/x-www-form-urlencoded";
        StreamWriter post = new StreamWriter(req.GetRequestStream());
        post.Write("field1=value1&field2=value2");
        post.Close();
        HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Avatar billede thesurfer Nybegynder
20. november 2007 - 12:27 #11
Da jeg ikke kan bestemme over andres websider, lavede jeg min egen ASP.NET webside.

Det er koden fra 19/11-2007 23:01:48 sammen med rettelserne fra 19/11-2007 23:07:13.

Nu skulle websitet gerne tage imod brugernavn og kodeord, via GET/URL/QueryString.

Hvis dette er forkert, sig endelig til, så jeg kan rette det.


Jeg synes ikke at jeg kan se nogen session, cookie container el.ligende, i indlægget 20/11-2007 02:58:17?
Avatar billede arne_v Ekspert
20. november 2007 - 15:32 #12
Det er korrekt. Det skal "blandes" med de andre eksempler.

Hvis det er en ASP.NET side skal du lige checke om der er noget "mere" end bare de
to felter som skal med over.

Jeg kan evt. proeve at bixe et eksempel med .NET i begge ender. Men nok foerst i morgen.

Det foerste stykke kode er et fungerende kode. Men server side er lavet saa den er
meget "samarbejdsvillig".
Avatar billede thesurfer Nybegynder
26. november 2007 - 22:02 #13
Det haster ikke.. Jeg er tilbage omkring fredag d. 30 november 2007..
Avatar billede thesurfer Nybegynder
03. december 2007 - 10:30 #14
Any luck? :-)
Avatar billede arne_v Ekspert
03. december 2007 - 18:31 #15
ups

nej - dette spoergsmaal var ligesom forsvundet fra radar skaermen - sorry

jeg maa proeve at finde noget tid til at kigge paa det
Avatar billede arne_v Ekspert
25. december 2007 - 22:55 #16
Så fik jeg langt om længe tid til at kigge på det.

ASP.NET web forms er lidt mere komplekse end de fleste andre login forme så.

Følgende virker hos mig:

using System;
using System.IO;
using System.Net;
using System.Web;
using System.Text.RegularExpressions;

namespace E
{
    public class MainClass
    {
        public static string Get(string url, CookieContainer session)
        {
            HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
            wr.Method = "GET";
            wr.CookieContainer = session;         
            string html = (new StreamReader(wr.GetResponse().GetResponseStream())).ReadToEnd();
            return html;
        }
        public static string Post(string url, string fields, CookieContainer session)
        {
            HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
            wr.Method = "POST";
            wr.CookieContainer = session;         
            wr.ContentType = "application/x-www-form-urlencoded";
            StreamWriter post = new StreamWriter(wr.GetRequestStream());
            post.Write(fields);
            post.Close();
            string html = (new StreamReader(wr.GetResponse().GetResponseStream())).ReadToEnd();
            return html;
        }
        public static void Main(string[] args)
        {
            CookieContainer session = new CookieContainer();
            string first = Get("http://localhost/noget.aspx", session);
            Console.WriteLine(first);
            string viewstate = HttpUtility.UrlEncode(Regex.Matches(first,"(?:<input type=\"hidden\" name=\"__VIEWSTATE\" id=\"__VIEWSTATE\" value=\")([^\"]*)(\" />)")[0].Groups[1].Value);
            string eventvalidation = HttpUtility.UrlEncode(Regex.Matches(first,"(?:<input type=\"hidden\" name=\"__EVENTVALIDATION\" id=\"__EVENTVALIDATION\" value=\")([^\"]*)(\" />)")[0].Groups[1].Value);
            Console.WriteLine(viewstate);
            Console.WriteLine(eventvalidation);
            string login = Post("http://localhost/Login.aspx?ReturnUrl=%2fnoget.aspx",
                                "__EVENTTARGET=&__EVENTARGUMENT=&Login1%24UserName=mig&Login1%24Password=hemmeligt&__VIEWSTATE=" + viewstate + "&Login1%24LoginButton=Log+In&__EVENTVALIDATION=" + eventvalidation, session);
            Console.WriteLine(login);
            string second = Get("http://localhost/nogetandet.aspx", session);
            Console.WriteLine(second);
            Console.ReadKey();
        }
    }
}
Avatar billede thesurfer Nybegynder
26. december 2007 - 07:10 #17
Hmmm...

Hos mig siger den:

The type or namespace name 'HttpUtility' does not exist in the namespace 'System.Web' (are you missing an assembly reference?)

Namespacet "System.Web;" er jo inkluderet via: using System.Web;

Jeg bruger Microsoft Visual Studio 2005 og har oprettet et console-projekt.. Jeg har prøvet at skrive det som "System.Web.HttpUtility" hvilket heller ikke virker.. logisk nok..
Avatar billede thesurfer Nybegynder
26. december 2007 - 07:13 #18
Ahh.. jeg tilføjede en reference til System.Web, og så forsvandt fejlen med 'HttpUtility'.. jeg troede ellers at "System.Web" var tilføjet..
Avatar billede thesurfer Nybegynder
26. december 2007 - 21:07 #19
Jeg får fejlen "Fjernserveren returnerede en fejl: (500) Intern serverfejl." i denne linie:

string html = (new StreamReader(wr.GetResponse().GetResponseStream())).ReadToEnd();


Jeg håber at du kan se noget forkert i koden, for det kan jeg ikke lige.. :-)

Måske er der nogle bestemte indstillinger jeg mangler..


Min kode ser sådan ud:



***** login.aspx:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="login.aspx.cs" Inherits="login" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        Username: <asp:TextBox ID="UserName" runat="server"></asp:TextBox>
        <br />
        Password: <asp:TextBox ID="Password" runat="server"></asp:TextBox>
        <br />
        <asp:Button ID="LoginButton" runat="server" Text="Log In" />
    </div>
    </form>
</body>
</html>



***** Program.cs:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Web;

namespace E
{
    class MainClass
    {
        private static string myhost = "http://localhost:34349/web_01/";
        private static string loginurl = myhost + "login.aspx";

        public static string Get(string url, CookieContainer session)
        {
            HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
            wr.Method = "GET";
            wr.CookieContainer = session;         
            string html = (new StreamReader(wr.GetResponse().GetResponseStream())).ReadToEnd();
            return html;
        }
        public static string Post(string url, string fields, CookieContainer session)
        {
            HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
            wr.Method = "POST";
            wr.CookieContainer = session;         
            wr.ContentType = "application/x-www-form-urlencoded";
            StreamWriter post = new StreamWriter(wr.GetRequestStream());
            post.Write(fields);
            post.Close();
            string html = (new StreamReader(wr.GetResponse().GetResponseStream())).ReadToEnd();
            return html;
        }
        public static void Main(string[] args)
        {

            CookieContainer session = new CookieContainer();
            string first = Get(loginurl, session);
            Console.WriteLine(first);
           
            string viewstate = HttpUtility.UrlEncode(Regex.Matches(first,"(?:<input type=\"hidden\" name=\"__VIEWSTATE\" id=\"__VIEWSTATE\" value=\")([^\"]*)(\" />)")[0].Groups[0].Value);
            string eventvalidation = HttpUtility.UrlEncode(Regex.Matches(first,"(?:<input type=\"hidden\" name=\"__EVENTVALIDATION\" id=\"__EVENTVALIDATION\" value=\")([^\"]*)(\" />)")[0].Groups[0].Value);
            Console.WriteLine(viewstate);
            Console.WriteLine(eventvalidation);
            string login = Post(loginurl,
                                "__EVENTTARGET=&__EVENTARGUMENT=&Login1%24UserName=mig&Login1%24Password=hemmeligt&__VIEWSTATE=" + viewstate + "&Login1%24LoginButton=Log+In&__EVENTVALIDATION=" + eventvalidation, session);
            Console.WriteLine(login);
            string second = Get(myhost + "nogetandet.aspx", session);
            Console.WriteLine(second);
            Console.ReadKey();
        }
    }
}


Jeg har udkommenteret Load-koden i til codebehing til login.aspx:

***** login.aspx.cs:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class login : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        //if (IsPostBack)
        //{
        //    string u = UserName.Text;
        //    string p = Password.Text;
        //    if (u == "a" && p == "b")
        //    {
        //        Session["login"] = "ok";
        //        if (Request.QueryString["ReturnUrl"] != null)
        //        {
        //            Response.Redirect("" + Request.QueryString["ReturnUrl"]);
        //        }
        //    }
        //    else
        //    {
        //        Session["login"] = "";
        //        Response.Write("Error in username or password");
        //    }
        //}
    }
}
Avatar billede thesurfer Nybegynder
26. december 2007 - 21:12 #20
Jeg har lige prøvet at unescape strengen der postes, og kan se at du bruger:

Login1$UserName
Login1$Password

Jeg går ud fra din form så har id "Login1".

Jeg har prøvet at ændre formens id fra "form" og til "Login1", men får samme fejl:

<form id="Login1" runat="server">

Hvis jeg loader login siden i browseren og kigger i kildekoden, ser jeg denne kode:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>
    Untitled Page
</title></head>
<body>
    <form name="Login1" method="post" action="login.aspx" id="Login1">
<div>
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTExNTc2NTI3OTlkZE6zy4eVK7VvMTwADX5uaTTEXXTQ" />
</div>

    <div>
        Username: <input name="UserName" type="text" id="UserName" />
        <br />
        Password: <input name="Password" type="text" id="Password" />
        <br />
        <input type="submit" name="LoginButton" value="Log In" id="LoginButton" />
    </div>
   
<div>

    <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWBALBnYGLCQKvruq2CALSxeCRDwL+jNCfD0Rba7fY8CZiUSt+lK4lLuJdj2hJ" />
</div></form>
</body>
</html>

Så vidt jeg kan se, får de ikke navnene:
Login1$UserName
Login1$Password

...?
Avatar billede arne_v Ekspert
26. december 2007 - 22:01 #21
Nej. Så skal du bruge de rigtige form navne.

Min Login.aspx ser ud som:

<%@ Page Language="C#" %>
<form runat=server>
<asp:Login ID="Login1" runat="server"/>
</form>

og så får den de navne jeg viser.
Avatar billede thesurfer Nybegynder
27. december 2007 - 00:11 #22
Jeg har lavet det om til asp:Login.. men får stadigvæk samme fejl..

Jeg har lagt mærke til at viewstate indeholder følgende:

"%3cinput+type%3d%22hidden%22+name%3d%22__VIEWSTATE%22+id%3d%22__VIEWSTATE%22+value%3d%22%2fwEPDwUJMTQ0ODE0ODM2ZBgBBR5fX0NvbnRyb2xzUmVxdWlyZVBvc3RCYWNrS2V5X18WAgURTG9naW4xJFJlbWVtYmVyTWUFF0xvZ2luMSRMb2dpbkltYWdlQnV0dG9uXSOWeoy2ZeHQ%2f7ePvyLt1%2fOJFZo%3d%22+%2f%3e"

Skal den det? jeg mener det med input-feltet og hvilke parametere det har og ikke kun viewstate-krypteret-tekst ?
Avatar billede arne_v Ekspert
27. december 2007 - 01:04 #23
Nej. Der er gået noget galt i regex'en.
Avatar billede thesurfer Nybegynder
24. juni 2009 - 15:41 #24
Hej arne_v

Er det ok med dig, hvis jeg lukker den her tråd, og starter en ny tråd? - sig endeligt til, hvis du vil have points (du har jo hjulpet med kode)..

Jeg er støt ind i et "Cookies is disabled" problem, og det er nok nemmeste at starte en ny tråd.. jeg prøver nu på at logge på Facebook..
Avatar billede arne_v Ekspert
28. juni 2009 - 20:31 #25
FB burde være nemmere, da den er PHP og ikke ASP.NET !

Fallback uden cookies en session ID i URL.

Jeg smider et svar og så må du jo vurdere om kode stumperne er point værd.
Avatar billede thesurfer Nybegynder
28. juni 2009 - 23:39 #26
Hvad med du med "Fallback uden cookies en session ID i URL" ?


Jeg smider points efter dig, da kodestumperne kan bruges.
Avatar billede arne_v Ekspert
28. juni 2009 - 23:46 #27
Hvis cookies ikke er enablet saa putter man tit session id i URL.
Avatar billede arne_v Ekspert
28. juni 2009 - 23:48 #28
I.s.f. en cookie:

xsessionid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

så haegtes den paa URL:

?foo=bar&xsessionid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester