2017-01-05 1 views
3

Ich habe eine Website mit Anzeigenauthentifizierung auf iis7 genommen und sie nach iis 8.5 migriert. Ich habe dabei versucht, zur Formularauthentifizierung zu wechseln. Nicht jede Seite der Site ist eine aspx-Seite - dort sind statische Inhalte und Dateien vorhanden, da es sich um eine Intranetsite handelt - aber die grundlegende Formularauthentifizierung hat funktioniert, weil ich den App-Pool auf den integrierten Modus gesetzt und web.config auf gesetzt habe Verwenden Sie die Formularauthentifizierung. Ich bin ziemlich froh, dass wenn Sie versuchen, so viel wie ein pdf zu laden, es sicherstellen wird, dass Sie zuerst in einem cas-Server angemeldet sind.Ich kann die Seiten zum Laden von Benutzerrollen aus Cookies nicht abrufen.

Mein Problem ist mit Rollen - Ich habe den Cookie auf der Anmeldeseite eingerichtet, um Rollen darin zu haben (die ich aus CAS-Attributen extrahiere), und wenn ich eine User.IsInRole() auf dieser Seite mache, heißt das Ja, die Person hat die Rolle. Aber wenn ich auf eine neue Seite, aspx oder nicht, gehe, ist die Person immer noch authentifiziert, hat aber nicht die Rolle. Ich versuche, den Rollenmanager zu vermeiden, weil ich nicht mit dem Provider umgehen will (der CAS-Server behandelt das Authentifizierungsstück), aber ich werde den Rollenmanager verwenden, wenn ich muss. Bis jetzt hatte ich Pech. Ich glaube, dass die Rollen nicht von den Cookies geladen werden, weil ich das gleiche (User.IsInRole ("Mitarbeiter"))? "True": "False"; Zeile auf der Hauptseite wie unten, aber auf der Login-Seite gibt es wahr und auf der Hauptseite gibt es false zurück.

Ich füge meine Webkonfiguration und den relevanten Abschnitt meines Login-Seitencodes an.

Web config (nur ankündigen Ordner verwendet Rollen atm):

<?xml version="1.0" encoding="UTF-8"?> 
<configuration> 
    <system.webServer> 
    <modules> 
     <!-- Re-add auth modules (in their original order) to run for all static and dynamic requests --> 
     <remove name="FormsAuthentication" /> 
     <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" /> 
     <remove name="DefaultAuthentication" /> 
     <add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" /> 
     <remove name="RoleManager" /> 
     <add name="RoleManager" type="System.Web.Security.RoleManagerModule" /> 
     <remove name="UrlAuthorization" /> 
     <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" /> 
    </modules> 
    </system.webServer> 
    <system.web> 
    <authentication mode="Forms" /> 
    <authorization> 
     <deny users="?" /> 
     <allow users="*" /> 
    </authorization> 
    </system.web> 
    <location path="announce"> 
    <system.web> 
     <authorization> 
     <allow roles="staff, faculty" /> 
     <deny users="*" /> 
     </authorization> 
    </system.web> 
    </location> 
</configuration> 

Relevante Abschnitt Anmeldeseite Code hinter (die Umleitung kommentiert wird, so kann ich ihre Rollen sehen):

// Second time (back from CAS) there is a ticket= to validate 
    // CAS 3 doesn't list attributes through /serviceValidate, so lets build a SAML request and use that instead. 
    string SAMLstr = "<?xml version='1.0'?><SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">" + 
    "<SOAP-ENV:Header/><SOAP-ENV:Body><samlp:Request xmlns:samlp=\"urn:oasis:names:tc:SAML:1.0:protocol\" " + 
    "MajorVersion=\"1\" MinorVersion=\"1\" RequestID=\"_" + Request.ServerVariables["REMOTE_HOST"] + "." + DateTime.Now.Ticks + "\"" + 
    "IssueInstant=\"" + DateTime.Now + "\"><samlp:AssertionArtifact>" + tkt + "</samlp:AssertionArtifact>" + 
    "</samlp:Request></SOAP-ENV:Body></SOAP-ENV:Envelope>"; 
    string validateurl = CASHOST + "samlValidate?TARGET=" + service + "&ticket=" + tkt; 
    // Set up an xml document to catch the SAML responce and then parse it. 
    XmlDocument xmlDoc = new XmlDocument(); 
    xmlDoc.LoadXml(new WebClient().UploadString(validateurl, SAMLstr)); 
    // The response uses multiple namespaces, whee! 
    var nsmgr = new XmlNamespaceManager(xmlDoc.NameTable); 
    nsmgr.AddNamespace("s", "http://schemas.xmlsoap.org/soap/envelope/"); 
    nsmgr.AddNamespace("nsR", "urn:oasis:names:tc:SAML:1.0:protocol"); 
    nsmgr.AddNamespace("nsA", "urn:oasis:names:tc:SAML:1.0:assertion"); 
    // Let's see if they authed successfully: 
    if (xmlDoc.SelectSingleNode("/s:Envelope/s:Body/nsR:Response/nsR:Status/nsR:StatusCode", nsmgr).Attributes["Value"].Value == ("samlp:Success")) { 
    // They authenticated successfully; populate their id and roles. 
    string netid = xmlDoc.SelectSingleNode("/s:Envelope/s:Body/nsR:Response/nsA:Assertion/nsA:AuthenticationStatement/nsA:Subject/nsA:NameIdentifier", nsmgr).InnerText; 
    // Grab the "memberOf" attriubute - it contains a child node for each group distinguished name. 
    XmlNode memberOf = xmlDoc.SelectSingleNode("/s:Envelope/s:Body/nsR:Response/nsA:Assertion/nsA:AttributeStatement/nsA:Attribute[@AttributeName='memberOf']", nsmgr); 
    // I don't want to iterate through that, so I'll just grab all the text and split it with a regex to split up the OUs and DCs. 
    string[] groups = Regex.Split(memberOf.InnerText.ToLower().Substring(3), "cn=(.*?),ou="); 
    HttpContext.Current.User = new GenericPrincipal(new GenericIdentity(netid),new string[] {"staff", "union", "UTech"}); 

    // Splicing together the groups names but droping the OUs (every other entry) 
    string roles=groups[1]; 
    for (int x=3;x<groups.Length;x+=2) roles+="|"+groups[x]; 
    // Let's bake cookies with the netid, roles, and persistence. 1: Make the ticket. 
    FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, netid, DateTime.Now, DateTime.Now.AddMinutes(2880), isPersistent, roles, FormsAuthentication.FormsCookiePath); 
    // 2. Encrypt the ticket. 
    string hash = FormsAuthentication.Encrypt(ticket); 
    // 3. Turn the encrypted ticket into a cookie! 
    HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash); 
    // 4. Set expiration on the cookie to match the ticket. 
    if (ticket.IsPersistent) cookie.Expires = ticket.Expiration; 
    // 5. Put the cookie in the jar. 
    Response.Cookies.Add(cookie); 
    // We're done! Send them home. 
    // [TEMP, next 3 lines are debug] Response.Redirect(service + Session["backto"], true); 
    Label1.Text = "Welcome, "+netid+"!"; 
    Label2.Text = roles; 
    Label3.Text = (User.IsInRole("staff"))?"True":"False"; 

Antwort

0

Ich hasse es, meine eigene Frage zu beantworten, aber nach einer Woche, in der ich Tutorials durchsucht und gelesen habe, habe ich es herausgefunden.

Die Cookies und Formulare Authentifizierung in der obigen Frage waren in Ordnung; Der Grund dafür, dass die Rollen nicht geladen wurden, war, dass ich in meinem global.asax kein PostAuthenticateRequest hatte (und überhaupt kein global.asax hatte). This question war sehr hilfreich, nicht von der angenommenen Antwort, sondern von einem angehängten Artikel von P.Hoxha. Der hat 0 gewählt, aber ich habe gestimmt. Ein Microsoft-Tutorial war auch hilfreich mit Korrekturen für das, was in der Antwort, die ich upvoted, nicht funktioniert hat.

die global.asax Hinzufügen löste das Problem, indem Sie den PostAuthenticateRequest Fang und den Code unten ausgeführt wird, die Rollen zu laden:

<%@ Application Language="C#" %> 
<%@ Import Namespace="System.Security.Principal" %> 
<%@ Import Namespace="System.Threading" %> 

<script runat="server"> 
void Application_OnPostAuthenticateRequest(object sender, EventArgs e) { 
    HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName]; 
    if (authCookie == null || authCookie.Value == "") return; 
    FormsAuthenticationTicket authTicket; 
    try { 
    authTicket = FormsAuthentication.Decrypt(authCookie.Value); 
    } catch { 
    return; 
    } 

    // retrieve roles from UserData 
    string[] roles = authTicket.UserData.Split('|'); 

    if (Context.User != null) Context.User = new GenericPrincipal(Context.User.Identity, roles); 
} 
</script> 
Verwandte Themen