예제 #1
0
        /// <summary>
        /// Attempts to request a proxy ticket for the targetService specified and
        /// returns a URL appropriate for redirection to the targetService containing
        /// a ticket.
        /// </summary>
        /// <param name="targetService">The target service for proxy authentication</param>
        /// <param name="proxyTicketUrlParameter">
        /// The name of the ticket URL parameter expected by the target service (ticket by
        /// default)
        /// </param>
        /// <returns>The URL of the target service with a proxy ticket included</returns>
        public static string GetProxyRedirectUrl(string targetService, string proxyTicketUrlParameter)
        {
            CasAuthentication.Initialize();
            
            // Todo: Is ResolveUrl(...) appropriate/necessary?  If the URL starts with ~, it shouldn't require proxy authentication
            string resolvedUrl = ResolveUrl(targetService);
            string proxyTicket = CasAuthentication.GetProxyTicketIdFor(resolvedUrl);

            EnhancedUriBuilder ub = new EnhancedUriBuilder(resolvedUrl);
            ub.QueryItems[proxyTicketUrlParameter] = proxyTicket;

            return ub.Uri.AbsoluteUri;
        }
        /// <summary>
        /// EndRequest is used to trigger the appropriate redirection.  There are
        /// currently three scenarios that require special redirections.
        /// <list>
        ///     <item>
        ///         Request is unauthenticated and is being routed to the FormsLoginUrl
        ///         (typically caused by UrlAuthorizationModule).  This request needs to
        ///         be intercepted to change the 'ReturnUrl' parameter to 'serviceName'
        ///     </item>
        ///     <item>
        ///         Request contains a CAS ticket in the URL.  This request needs to be
        ///         redirected back to itself without the 'ticket' parameter in order to
        ///         avoid potential infinite automatic ticket validation loops for when
        ///         a the ticket in the URL has expired or was revoked and the Renew
        ///         configuration parameter is set.
        ///     </item>
        ///     <item>
        ///         Request is authenticated, but is not authorized to access the
        ///         requested resource (by UrlAuthorizationModule).  If the CAS is
        ///         configured with a NotAuthorizedUrl, the request is redirected to
        ///         that page.  Otherwise, it is redirected to the CAS login page with
        ///         a forced 'Renew' property (to prevent infinite redirect loops).
        ///     </item>
        /// </list>
        /// </summary>
        /// <param name="sender">The HttpApplication that sent the request</param>
        /// <param name="e">Not used</param>
        private static void OnEndRequest(object sender, EventArgs e)
        {
            if (!RequestEvaluator.GetRequestIsAppropriateForCasAuthentication())
            {
                logger.Debug("EndRequest bypassed for " + HttpContext.Current.Request.RawUrl);
                return;
            }

            HttpContext context = HttpContext.Current;
            HttpRequest request = context.Request;

            logger.Debug("Starting EndRequest for " + request.RawUrl);

            if (RequestEvaluator.GetRequestRequiresGateway())
            {
                logger.Info("  Performing Gateway Authentication");
                CasAuthentication.GatewayAuthenticate(true);
            }
            else if (RequestEvaluator.GetUserDoesNotAllowSessionCookies())
            {
                logger.Info("  Cookies not supported.  Redirecting to Cookies Required Page");
                CasAuthentication.RedirectToCookiesRequiredPage();
            }
            else if (RequestEvaluator.GetRequestHasCasTicket())
            {
                logger.Info("  Redirecting from login callback");
                CasAuthentication.RedirectFromLoginCallback();
            }
            else if (RequestEvaluator.GetRequestHasGatewayParameter())
            {
                logger.Info("  Redirecting from failed gateway callback");
                CasAuthentication.RedirectFromFailedGatewayCallback();
            }
            else if (RequestEvaluator.GetRequestIsUnauthorized() && !String.IsNullOrEmpty(CasAuthentication.NotAuthorizedUrl))
            {
                logger.Info("  Redirecting to Unauthorized Page");
                CasAuthentication.RedirectToNotAuthorizedPage();
            }
            else if (RequestEvaluator.GetRequestIsUnauthorized())
            {
                logger.Info("  Redirecting to CAS Login Page (Unauthorized without NotAuthorizedUrl defined)");
                CasAuthentication.RedirectToLoginPage(true);
            }
            else if (RequestEvaluator.GetRequestIsUnAuthenticated())
            {
                logger.Info("  Redirecting to CAS Login Page");
                CasAuthentication.RedirectToLoginPage();
            }

            logger.Debug("Ending EndRequest for " + request.RawUrl);
        }
예제 #3
0
        /// <summary>
        /// Determines whether the User associated with the request has been
        /// defined and is authenticated.
        /// </summary>
        /// <returns>True if the request has an authenticated User, otherwise False</returns>
        private static bool GetUserIsAuthenticated()
        {
            CasAuthentication.Initialize();

            HttpContext context = HttpContext.Current;

            bool result =
                (
                    context.User != null &&
                    context.User.Identity.IsAuthenticated
                );

            return(result);
        }
예제 #4
0
        /// <summary>
        /// Determines whether the current request is unauthenticated
        /// </summary>
        /// <returns>True if the request is unauthenticated, otherwise False</returns>
        internal static bool GetRequestIsUnAuthenticated()
        {
            CasAuthentication.Initialize();

            bool userIsNotAuthenticated     = !GetUserIsAuthenticated();
            bool responseIsCasLoginRedirect = GetResponseIsCasLoginRedirect();

            bool result =
                (
                    userIsNotAuthenticated &&
                    responseIsCasLoginRedirect
                );

            return(result);
        }
예제 #5
0
        /// <summary>
        /// Determines whether the request has a CAS ticket in the URL
        /// </summary>
        /// <returns>True if the request URL contains a CAS ticket, otherwise False</returns>
        internal static bool GetRequestHasCasTicket()
        {
            CasAuthentication.Initialize();

            HttpContext context = HttpContext.Current;
            HttpRequest request = context.Request;

            bool result =
                (
                    request[CasAuthentication.TicketValidator.ArtifactParameterName] != null &&
                    !String.IsNullOrEmpty(request[CasAuthentication.TicketValidator.ArtifactParameterName])
                );

            return(result);
        }
        /// <summary>
        /// Intercepts the beginning of the request pipeline.  This will detect SingleSignOut
        /// requests.  SingleSignOut requests are posted back to the serviceName URL that
        /// was passed when the CAS session was established.  Since the behavior of the script
        /// at that URL is unknown, a POST back by the CAS server could have unexpected
        /// consequences.  We want to prevent this request from authenticating and from
        /// executing the HttpHandler typically associated with that URL.  So we are handling
        /// this by sending back an HTTP 200 (OK) message with a blank body and short
        /// circuiting all event processing and firing EndRequest directly
        /// (via CompleteRequest()).
        /// </summary>
        /// <param name="sender">The HttpApplication that sent the request</param>
        /// <param name="e">Not used</param>
        private static void OnBeginRequest(object sender, EventArgs e)
        {
            // Validate the ticket coming back from the CAS server (NETC-55)
            if (!RequestEvaluator.GetRequestIsAppropriateForCasAuthentication())
            {
                logger.Debug("BeginRequest bypassed for " + HttpContext.Current.Request.RawUrl);
                return;
            }

            CasAuthentication.Initialize();

            HttpContext context = HttpContext.Current;
            HttpRequest request = context.Request;

            logger.Debug("Starting BeginRequest for " + request.RawUrl);

            // Cleanup expired ServiceTickets in the ServiceTicketManager
            if (CasAuthentication.ServiceTicketManager != null)
            {
                CasAuthentication.ServiceTicketManager.RemoveExpiredTickets();
            }

            // Cleanup expired ProxyTicket mappings in the ProxyTicketManager
            if (CasAuthentication.ProxyTicketManager != null)
            {
                CasAuthentication.ProxyTicketManager.RemoveExpiredMappings();
            }

            // Detect & process inbound Single SignOut Requests from the CAS server
            if (CasAuthentication.ServiceTicketManager != null && CasAuthentication.ProcessIncomingSingleSignOutRequests && RequestEvaluator.GetRequestIsCasSingleSignOut())
            {
                logger.Info("Processing inbound Single Sign Out request.");
                CasAuthentication.ProcessSingleSignOutRequest();
                return;
            }

            // Detect & process inbound proxy callback verifications from the CAS server

            if (CasAuthentication.ProxyTicketManager != null && RequestEvaluator.GetRequestIsProxyResponse())
            {
                logger.Info("Processing Proxy Callback request");
                CasAuthentication.ProcessProxyCallbackRequest();
                return;
            }

            logger.Debug("Ending BeginRequest for " + request.RawUrl);
        }
예제 #7
0
        /// <summary>
        /// Determines whether the request is for the CookiesRequiredUrl defined in web.config
        /// </summary>
        /// <returns>True if the request is to the CookiesRequiredUrl, otherwise False</returns>
        private static bool GetRequestIsCookiesRequiredUrl()
        {
            CasAuthentication.Initialize();

            HttpContext context = HttpContext.Current;
            HttpRequest request = context.Request;

            bool cookiesRequiredUrlIsDefined = !String.IsNullOrEmpty(CasAuthentication.CookiesRequiredUrl);
            bool requestIsCookiesRequiredUrl = cookiesRequiredUrlIsDefined && request.RawUrl.StartsWith(UrlUtil.ResolveUrl(CasAuthentication.CookiesRequiredUrl), true, CultureInfo.InvariantCulture);

            bool result =
                (
                    requestIsCookiesRequiredUrl
                );

            return(result);
        }
예제 #8
0
        /// <summary>
        /// Determines whether the request is an inbound proxy callback verifications
        /// from the CAS server
        /// </summary>
        /// <returns>True if the request is a proxy callback verificiation, otherwise False</returns>
        internal static bool GetRequestIsProxyResponse()
        {
            CasAuthentication.Initialize();

            HttpContext context = HttpContext.Current;
            HttpRequest request = context.Request;

            bool requestContainsProxyCallbackParameter = !String.IsNullOrEmpty(request.QueryString[CasAuthentication.ProxyCallbackParameterName]);
            bool proxyCallbackParameterValueIsTrue     = (request.QueryString[CasAuthentication.ProxyCallbackParameterName] == "true");

            bool result =
                (
                    requestContainsProxyCallbackParameter &&
                    proxyCallbackParameterValueIsTrue
                );

            return(result);
        }
예제 #9
0
        /// <summary>
        /// Determines whether the request contains the GatewayParameterName defined in
        /// web.config or the default value 'gatewayResponse'
        /// </summary>
        /// <returns>True if the request contains the GatewayParameterName, otherwise False</returns>
        internal static bool GetRequestHasGatewayParameter()
        {
            CasAuthentication.Initialize();

            HttpContext context = HttpContext.Current;
            HttpRequest request = context.Request;

            bool requestContainsGatewayParameter = !String.IsNullOrEmpty(request.QueryString[CasAuthentication.GatewayParameterName]);
            bool gatewayParameterValueIsTrue     = (request.QueryString[CasAuthentication.GatewayParameterName] == "true");

            bool result =
                (
                    requestContainsGatewayParameter &&
                    gatewayParameterValueIsTrue
                );

            return(result);
        }
예제 #10
0
        /// <summary>
        /// Determines whether the request is a CAS Single Sign Out request
        /// </summary>
        /// <returns>True if the request is a CAS Single Sign Out request, otherwise False</returns>
        internal static bool GetRequestIsCasSingleSignOut()
        {
            CasAuthentication.Initialize();

            HttpContext context = HttpContext.Current;
            HttpRequest request = context.Request;

            bool requestIsFormPost = (request.RequestType == "POST");
            bool haveLogoutRequest = !string.IsNullOrEmpty(request.Params["logoutRequest"]);

            bool result =
                (
                    requestIsFormPost &&
                    haveLogoutRequest
                );

            return(result);
        }
예제 #11
0
        /// <summary>
        /// Determines whether the request is appropriate for CAS authentication.
        /// Generally, this is true for most requests except those for images,
        /// style sheets, javascript files and anything generated by the built-in
        /// ASP.NET handlers (i.e., web resources, trace handler).
        /// </summary>
        /// <returns>True if the request is appropriate for CAS authentication, otherwise False</returns>
        internal static bool GetRequestIsAppropriateForCasAuthentication()
        {
            CasAuthentication.Initialize();

            HttpContext  context  = HttpContext.Current;
            HttpRequest  request  = context.Request;
            HttpResponse response = context.Response;

            string contentType = response.ContentType;
            string fileName    = request.Url.Segments[request.Url.Segments.Length - 1];

            bool contentTypeIsEligible = false;
            bool fileNameIsEligible    = true;

            if (string.IsNullOrEmpty(contentType) && CasAuthentication.RequireCasForMissingContentTypes)
            {
                contentTypeIsEligible = true;
            }

            if (!contentTypeIsEligible)
            {
                foreach (string appropriateContentType in CasAuthentication.RequireCasForContentTypes)
                {
                    if (string.Compare(contentType, appropriateContentType, true, CultureInfo.InvariantCulture) == 0)
                    {
                        contentTypeIsEligible = true;
                        break;
                    }
                }
            }

            foreach (string builtInHandler in CasAuthentication.BypassCasForHandlers)
            {
                if (string.Compare(fileName, builtInHandler, true, CultureInfo.InvariantCulture) == 0)
                {
                    fileNameIsEligible = false;
                    break;
                }
            }

            return(contentTypeIsEligible && fileNameIsEligible);
        }
예제 #12
0
        /// <summary>
        /// Determines whether the current request will be redirected to the
        /// CAS login page
        /// </summary>
        /// <returns>True if the request will be redirected, otherwise False.</returns>
        private static bool GetResponseIsCasLoginRedirect()
        {
            CasAuthentication.Initialize();

            HttpContext  context  = HttpContext.Current;
            HttpResponse response = context.Response;

            bool requestDoesNotHaveCasTicket      = !GetRequestHasCasTicket();
            bool responseIsBeingRedirected        = (response.StatusCode == 302);
            bool responseRedirectsToFormsLoginUrl = !String.IsNullOrEmpty(response.RedirectLocation) && response.RedirectLocation.StartsWith(CasAuthentication.FormsLoginUrl);

            bool result =
                (
                    requestDoesNotHaveCasTicket &&
                    responseIsBeingRedirected &&
                    responseRedirectsToFormsLoginUrl
                );

            return(result);
        }
예제 #13
0
        /// <summary>
        /// Determines whether the current request is unauthorized
        /// </summary>
        /// <returns>True if the request is unauthorized, otherwise False</returns>
        internal static bool GetRequestIsUnauthorized()
        {
            CasAuthentication.Initialize();

            HttpContext  context  = HttpContext.Current;
            HttpResponse response = context.Response;

            bool responseIsBeingRedirected  = (response.StatusCode == 302);
            bool userIsAuthenticated        = GetUserIsAuthenticated();
            bool responseIsCasLoginRedirect = GetResponseIsCasLoginRedirect();

            bool result =
                (
                    responseIsBeingRedirected &&
                    userIsAuthenticated &&
                    responseIsCasLoginRedirect
                );

            return(result);
        }
예제 #14
0
        /// <summary>
        /// Determines whether the request is a return request from the
        /// CAS server containing a CAS ticket
        /// </summary>
        /// <returns>True if the request URL contains a CAS ticket, otherwise False</returns>
        internal static bool GetRequestIsCasAuthenticationResponse()
        {
            CasAuthentication.Initialize();

            HttpContext context = HttpContext.Current;
            HttpRequest request = context.Request;

            int artifactIndex = request.Url.AbsoluteUri.IndexOf(CasAuthentication.TicketValidator.ArtifactParameterName);

            bool result =
                (
                    GetRequestHasCasTicket() &&
                    artifactIndex > 0 &&
                    (
                        request.Url.AbsoluteUri[artifactIndex - 1] == '?' ||
                        request.Url.AbsoluteUri[artifactIndex - 1] == '&'
                    )
                );

            return(result);
        }
예제 #15
0
        public ActionResult Out()
        {
            HttpCookie ticketCookie = Request.Cookies[FormsAuthentication.FormsCookieName];

            if (ticketCookie != null)
            {
                FormsAuthenticationTicket ticket    = FormsAuthentication.Decrypt(ticketCookie.Value);
                CasAuthenticationTicket   casTicket = CasAuthentication.ServiceTicketManager.GetTicket(ticket.UserData);

                CasAuthentication.ServiceTicketManager.RevokeTicket(casTicket.ServiceTicket);

                CasAuthentication.ClearAuthCookie();
                FormsAuthentication.SignOut();
                Request.Cookies.Remove(FormsAuthentication.FormsCookieName);
                Response.Cookies.Remove(FormsAuthentication.FormsCookieName);
                Session.RemoveAll();
                //会回调客户端
                CasAuthentication.SingleSignOut();
            }
            return(Content("退出成功,获取当前用户信息:" + User.Identity.IsAuthenticated));
        }
예제 #16
0
        /// <summary>
        /// Constructs a proxy ticket request URL containing both a proxy granting 
        /// ticket and a URL Encoded targetServiceUrl.  The URL returned will generally only
        /// be executed by the CAS client as a part of a proxy redirection in 
        /// CasAuthentication.ProxyRedirect(...) or CasAuthentication.GetProxyTicketIdFor(...)
        /// but may also be used by applications which require low-level access to the proxy
        /// ticket request functionality.
        /// </summary>
        /// <param name="proxyGrantingTicketId">
        /// The proxy granting ticket used to authorize the request for a proxy ticket on the 
        /// CAS server
        /// </param>
        /// <param name="targetService">
        /// The target service URL to request a proxy ticket request URL for
        /// </param>
        /// <returns>The URL to use to request a proxy ticket for the targetService specified</returns>
        public static string ConstructProxyTicketRequestUrl(string proxyGrantingTicketId, string targetService)
        {
            CasAuthentication.Initialize();

            if (String.IsNullOrEmpty(proxyGrantingTicketId))
            {
                throw new ArgumentException("For proxy ticket requests, proxyGrantingTicketId cannot be null and must be specified.");
            }

            if (String.IsNullOrEmpty(targetService))
            {
                throw new ArgumentException("For proxy ticket requests, targetService cannot be null and must be specified.");
            }

            // TODO: Make "proxy" configurable.
            EnhancedUriBuilder ub = new EnhancedUriBuilder(EnhancedUriBuilder.Combine(CasAuthentication.CasServerUrlPrefix, "proxy"));
            ub.QueryItems.Add("pgt", proxyGrantingTicketId);
            ub.QueryItems.Add("targetService", HttpUtility.UrlEncode(targetService));

            return ub.Uri.AbsoluteUri;
        }
예제 #17
0
        /// <summary>
        /// Resolves a relative ~/Url to a Url that is meaningful to the
        /// client.
        /// <remarks>
        /// Derived from: http://weblogs.asp.net/palermo4/archive/2004/06/18/getting-the-absolute-path-in-asp-net-part-2.aspx
        /// </remarks>        
        /// </summary>
        /// <author>J. Michael Palermo IV</author>
        /// <author>Scott Holodak</author>
        /// <param name="url">The Url to resolve</param>
        /// <returns>The fullly resolved Url</returns>
        internal static string ResolveUrl(string url)
        {
            CommonUtils.AssertNotNullOrEmpty(url, "url parameter can not be null or empty.");
            if (url[0] != '~') return url;

            CasAuthentication.Initialize();

            string applicationPath = HttpContext.Current.Request.ApplicationPath;
            if (url.Length == 1) return applicationPath;

            // assume url looks like ~somePage 
            int indexOfUrl = 1;

            // determine the middle character 
            string midPath = ((applicationPath ?? string.Empty).Length > 1) ? "/" : string.Empty;

            // if url looks like ~/ or ~\ change the indexOfUrl to 2 
            if (url[1] == '/' || url[1] == '\\') indexOfUrl = 2;

            return applicationPath + midPath + url.Substring(indexOfUrl);
        }    
예제 #18
0
        /// <summary>
        /// Constructs a service URL using configured values in the following order:
        /// 1.  if not empty, the value configured for Service is used
        /// - otherwise -
        /// 2.  the value configured for ServerName is used together with HttpRequest
        ///     data
        /// </summary>
        /// <remarks>
        /// The server name is not parsed from the request for security reasons, which
        /// is why the service and server name configuration parameters exist, per Apereo
        /// website.
        /// </remarks>
        /// <returns>the service URL to use, not encoded</returns>
        public static string ConstructServiceUrl(bool gateway)
        {
            CasAuthentication.Initialize();

            HttpContext context = HttpContext.Current;
            HttpRequest request = context.Request;

            StringBuilder buffer = new StringBuilder();

            if (!(CasAuthentication.ServerName.StartsWith("https://") || CasAuthentication.ServerName.StartsWith("http://")))
            {
                buffer.Append(request.IsSecureConnection ? "https://" : "http://");
            }
            buffer.Append(CasAuthentication.ServerName);

            EnhancedUriBuilder ub = new EnhancedUriBuilder(buffer.ToString());

            ub.Path = request.Url.AbsolutePath;

            // Iterate through each of the name/value pairs in the query component of the service URL
            foreach (string name in request.QueryString.AllKeys)
            {
                // URL encode each name/value pair and then add it to the query items collection
                ub.QueryItems.Add(HttpUtility.UrlEncode(name), HttpUtility.UrlEncode(request.QueryString[name]));
            }

            ub.QueryItems.Remove(CasAuthentication.TicketValidator.ServiceParameterName);
            ub.QueryItems.Remove(CasAuthentication.TicketValidator.ArtifactParameterName);

            if (gateway)
            {
                ub.QueryItems.Set(CasAuthentication.GatewayParameterName, "true");
            }
            else
            {
                ub.QueryItems.Remove(CasAuthentication.GatewayParameterName);
            }
            return(ub.Uri.AbsoluteUri);
        }
예제 #19
0
        /// <summary>
        /// Handles the authentication of the request.
        ///
        /// If the request contains a ticket, this will validate the ticket and create a
        /// FormsAuthenticationTicket and encrypted cookie container for it.  It will redirect
        /// to remove the ticket from the URL.  With Forms-based authentication, this is
        /// required to prevent the client from automatically/silently re-authenticating on a
        /// refresh or after logout.
        ///
        /// If the request does not contain a ticket, it checks for a FormsAuthentication
        /// cookie, decrypts it, extracts the FormsAuthenticationTicket, verifies that it
        /// exists in the StateProvider/ServiceTicketManager, and assigns a Principal to the
        /// thread and context.User properties.  All events after this request become
        /// authenticated.
        /// </summary>
        /// <param name="sender">The HttpApplication that sent the request</param>
        /// <param name="e">Not used</param>
        private static void OnAuthenticateRequest(object sender, EventArgs e)
        {
            HttpContext context = HttpContext.Current;
            HttpRequest request = context.Request;

            // Validate the ticket coming back from the CAS server
            if (!RequestEvaluator.GetRequestIsAppropriateForCasAuthentication())
            {
                logger.Debug("AuthenticateRequest bypassed for " + request.RawUrl);
                return;
            }

            // Validate the ticket coming back from the CAS server
            if (RequestEvaluator.GetRequestHasCasTicket())
            {
                logger.Info("Processing Proxy Callback request");
                CasAuthentication.ProcessTicketValidation();
            }

            logger.Debug("Starting AuthenticateRequest for " + request.RawUrl);
            CasAuthentication.ProcessRequestAuthentication();
            logger.Debug("Ending AuthenticateRequest for " + request.RawUrl);
        }
예제 #20
0
        /// <summary>
        /// 退出
        /// </summary>
        /// <returns></returns>
        public ActionResult LogOut()
        {
            HttpCookie ticketCookie = Request.Cookies[FormsAuthentication.FormsCookieName];

            if (ticketCookie != null)
            {
                //获取form auth令牌信息,用以进行令牌清除
                FormsAuthenticationTicket ticket    = FormsAuthentication.Decrypt(ticketCookie.Value);
                CasAuthenticationTicket   casTicket = CasAuthentication.ServiceTicketManager.GetTicket(ticket.UserData);

                CasAuthentication.ServiceTicketManager.RevokeTicket(casTicket.ServiceTicket);
                CasAuthentication.ClearAuthCookie();

                //移除本地cookie及session
                FormsAuthentication.SignOut();
                Request.Cookies.Remove(FormsAuthentication.FormsCookieName);
                Response.Cookies.Remove(FormsAuthentication.FormsCookieName);
                //cas登出,调用此方法时,远端cas server会再次回调此url
                CasAuthentication.SingleSignOut();
            }
            Session.RemoveAll();
            return(RedirectToAction("Login", "Currency"));
        }
예제 #21
0
        /// <summary>
        /// The implementation uses the CAS clearPass extension to obtain the user's password
        /// by requesting a proxy ticket for clearPass and parsing out the user's password that
        /// is returned as part of the response enclosed within <![CDATA[<cas:credentials>]]> elements.
        /// Returned object is a SecureString.
        /// </summary>
        public SecureString GetSecurePassword()
        {
            EnhancedUriBuilder clearPassUri = new EnhancedUriBuilder(CasAuthentication.CasServerUrlPrefix);

            clearPassUri.Path += "clearPass";

            string proxyTicket = CasAuthentication.GetProxyTicketIdFor(clearPassUri.Uri.AbsoluteUri);

            if (string.IsNullOrEmpty(proxyTicket))
            {
                throw new HttpException("Unable to obtain CAS Proxy Ticket for clearPass.");
            }

            clearPassUri.QueryItems.Add(CasClientConfiguration.Config.ArtifactParameterName, proxyTicket);

            var secureClearPassResponse = new SecureString();

            try
            {
                var body = String.Format(CasClientConfiguration.Config.ClearPassGetRequest, clearPassUri.Uri.PathAndQuery, clearPassUri.Uri.Authority);

                secureClearPassResponse = SecureClient.SecureHttpRequest(clearPassUri.Uri, body, 2000);

                if (secureClearPassResponse.Length == 0)
                {
                    throw new HttpException("ClearPass service returned an empty response.");
                }
            }
            catch (Exception e)
            {
                throw new HttpException(
                          "Unable to obtain clearPass response from CAS. Review CAS logs and ensure the proxy chain is configured correctly.",
                          e);
            }

            // Marshall into plaintext and return final
            var securePassword = new SecureString();

            // Setup pinned variables in memory
            var insecureClearPassResponse = "";
            var insecurePassword          = "";
            var unmanagedString           = IntPtr.Zero;

            var gcHandler  = GCHandle.Alloc(insecureClearPassResponse, GCHandleType.Pinned);
            var pwHandler  = GCHandle.Alloc(insecurePassword, GCHandleType.Pinned);
            var ptrHandler = GCHandle.Alloc(unmanagedString, GCHandleType.Pinned);

            try
            {
                var xmlReaderSetting = new XmlReaderSettings
                {
                    ConformanceLevel = ConformanceLevel.Auto,
                    IgnoreWhitespace = true
                };

                unmanagedString           = Marshal.SecureStringToGlobalAllocUnicode(secureClearPassResponse);
                insecureClearPassResponse = Marshal.PtrToStringUni(unmanagedString);

                if (insecureClearPassResponse == null)
                {
                    throw new AccessViolationException("ClearPass response was erased from memory.");
                }

                using (TextReader stringReader = new StringReader(insecureClearPassResponse))
                {
                    using (var xmlReader = XmlReader.Create(stringReader, xmlReaderSetting))
                    {
                        try
                        {
                            if (xmlReader.ReadToFollowing("cas:credentials"))
                            {
                                insecurePassword = xmlReader.ReadElementString();

                                foreach (char t in insecurePassword)
                                {
                                    securePassword.AppendChar(t);
                                }
                            }

                            if (securePassword.Length == 0)
                            {
                                throw new HttpException(
                                          "No password was received from CAS. Review clearPass configuration for CAS and ensure the feature is turned on");
                            }
                        }
                        finally
                        {
                            // Scrub insecure variables
                            insecurePassword          = null;
                            insecureClearPassResponse = null;

                            // Explicitly close and dispose xmlReader
                            xmlReader.Close();
                            ((IDisposable)xmlReader).Dispose();

                            // Explicitly close and dispose TextReader
                            stringReader.Close();
                            stringReader.Dispose();
                        }
                    }
                }
            }

            // Ensure cleanup
            finally
            {
                pwHandler.Free();
                gcHandler.Free();
                ptrHandler.Free();

                Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
            }

            return(securePassword);
        }
예제 #22
0
        /// <summary>
        /// Using ProxyTickets and the ClearPass extension for CAS CasOwaAuthHandler retrieves
        /// the users credentials, POSTs them to the OWA, retrieves sessionid and cdata cookies,
        /// sets them on the browser and redirects to the user's inbox.
        /// </summary>
        /// <param name="context"></param>
        public void ProcessRequest(HttpContext context)
        {
            ICasPrincipal user = context.User as ICasPrincipal;

            if (user == null)
            {
                throw new HttpException(500, "HttpContext.Current.User is null.  Check that the DotNetCasClient is mapped and configured correctly in <web.conf>");
            }


            // Retrieve a Proxy Ticket for ClearPass
            string proxyTicket = CasAuthentication.GetProxyTicketIdFor(ClearPassUrl);

            if (log.IsDebugEnabled)
            {
                log.Debug("Proxy ticket received for clearpass: "******"?" + ArtifactParameterName + "=" + proxyTicket + "&" + ServiceParameterName + "=" + ClearPassUrl;
            string clearPassResponse;

            try
            {
                using (StreamReader reader = new StreamReader(new WebClient().OpenRead(clearPassRequest)))
                    clearPassResponse = reader.ReadToEnd();
            }
            catch (Exception ex)
            {
                throw new HttpException(500, "Error getting response from clearPass at URL: " + clearPassRequest + ". " + ex.Message, ex);
            }

            string clearPass = XmlUtils.GetTextForElement(clearPassResponse, "cas:credentials");

            if (String.IsNullOrEmpty(clearPass))
            {
                throw new HttpException(500, "Received response from " + clearPassRequest + ", but cas:credientials IsNullOrEmpty.  Check CAS server logs for errors.  Make sure SSL certs are trusted.");
            }

            // POST username/password to owaauth.dll to get sessionid and cadata cookies
            var owaAuthFormFields = "destination=" + OwaUrl
                                    + "&username="******"&password="******"POST";
            request.ContentType       = "application/x-www-form-urlencoded";
            request.ContentLength     = postData.Length;
            request.UserAgent         = "Mozilla/5.0+(compatible;+MSIE+9.0;+Windows+NT+6.1;+WOW64;+Trident/5.0)";

            try
            {
                using (Stream requestStream = request.GetRequestStream())
                    requestStream.Write(postData, 0, postData.Length);
            }
            catch (Exception ex)
            {
                if (log.IsErrorEnabled)
                {
                    log.Error(ex.Message, ex);
                }

                throw new HttpException(500, "Error POSTing Auth Form to " + OwaUrl + OwaAuthPath + ". " + ex.Message, ex);
            }

            try
            {
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    if (log.IsDebugEnabled)
                    {
                        log.Debug("# of OWA cookies received: " + response.Cookies.Count);
                    }


                    // Send sessionid and cadata cookies back to the browser and redirect to Owa
                    foreach (Cookie cookie in response.Cookies)
                    {
                        context.Response.Cookies.Add(new HttpCookie(cookie.Name, cookie.Value));
                    }

                    string redirectUrl;
                    if (String.IsNullOrEmpty(OwaInboxUrl))
                    {
                        redirectUrl = response.GetResponseHeader("Location");
                    }
                    else
                    {
                        redirectUrl = OwaInboxUrl;
                    }

                    if (log.IsDebugEnabled)
                    {
                        log.Debug("Added all auth cookies. Redirecting to " + redirectUrl);
                    }

                    context.Response.Redirect(redirectUrl);
                }
            }
            catch (Exception ex)
            {
                if (log.IsErrorEnabled)
                {
                    log.Error(ex.Message, ex);
                }

                throw new HttpException(500, "Error getting Response from " + OwaUrl + OwaAuthPath + ". " + ex.Message, ex);
            }
        }
예제 #23
0
        /// <summary>
        /// Using CAS ProxyTickets and the ClearPass extention for CAS, CasAngelClient retrieves
        /// the users credentials, POSTs them to the Angel REST API ATHENICATION_PASS, retrieves
        /// a SSO token and URL and redirect's the user to Angel.
        /// </summary>
        /// <param name="context"></param>
        public void ProcessRequest(HttpContext context)
        {
            // Make sure we have an authenticated user
            if (!context.User.Identity.IsAuthenticated)
            {
                throw new HttpException(500, "HttpContext.Current.User is not authenticated.  Check that the DotNetCasClient is mapped and configured correctly in <web.conf>");
            }

            // Get clear text pasword via ClassPass if we are using AngelApiValidate
            string clearPass = "";

            if (AngelApiValidate)
            {
                // Retrieve a Proxy Ticket for ClearPass
                string proxyTicket = CasAuthentication.GetProxyTicketIdFor(ClearPassUrl);

                // Get the Password from ClearPass
                string       clearPassResponse;
                WebClient    clearPassWebClient = null;
                StreamReader reader             = null;
                try
                {
                    clearPassWebClient             = new WebClient();
                    clearPassWebClient.QueryString = new NameValueCollection
                    {
                        { "ticket", proxyTicket }, { "service", ClearPassUrl }
                    };
                    reader            = new StreamReader(clearPassWebClient.OpenRead(ClearPassUrl));
                    clearPassResponse = reader.ReadToEnd();
                }
                catch (Exception ex)
                {
                    throw new HttpException(500,
                                            "Error getting response from clearPass at URL: " + ClearPassUrl + ". " +
                                            ex.Message, ex);
                }
                finally
                {
                    if (reader != null)
                    {
                        reader.Dispose();
                    }
                    if (clearPassWebClient != null)
                    {
                        clearPassWebClient.Dispose();
                    }
                }

                clearPass = GetTextForElement(clearPassResponse, "cas:credentials");
                if (String.IsNullOrEmpty(clearPass))
                {
                    throw new HttpException(500,
                                            "cas:credientials not found in clearPassResponse.  Check CAS server logs for errors.  Make sure SSL certs are trusted.");
                }
            }

            // Authenticate against Angel and retrieve redirect URL
            string strPost = "APIACTION=AUTHENTICATION_PASS&APIUSER="******"&APIPWD=" + AngelApiPassword
                             + "&USER="******"&PASSWORD="******"&VALIDATE=" + (AngelApiValidate ? "1" : "0"); // validate forces Angel to check users credentials
            string angelApiResponse = PerformHttpPost(AngelApiUrl, strPost, false);
            string redirectUrl      = GetTextForElement(angelApiResponse, "success");

            if (String.IsNullOrEmpty(redirectUrl))
            {
                throw new HttpException(500, "Angel AUTHENTICATION_PASS failed for user: "******".  AngelAPI Error: " + GetTextForElement(angelApiResponse, "error"));
            }
            FormsAuthentication.SignOut();
            context.Response.Redirect(redirectUrl);
        }
예제 #24
0
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                FormsAuthenticationTicket formsAuthTicket = CasAuthentication.GetFormsAuthenticationTicket();
                CasAuthenticationTicket   casTicket       = CasAuthentication.ServiceTicketManager.GetTicket(formsAuthTicket.UserData);

                string validateUrl = EnhancedUriBuilder.Combine(CasAuthentication.CasServerUrlPrefix, "proxyValidate");

                Uri    url = new UriBuilder(Request.Url.Scheme, Request.Url.DnsSafeHost, ((Request.IsSecureConnection && Request.Url.Port == 443) || (!Request.IsSecureConnection && Request.Url.Port == 80)) ? -1 : Request.Url.Port, ResolveUrl("DotNetCasProxyDemoApp.application")).Uri;
                string proxyGrantingTicket = casTicket.ProxyGrantingTicket;
                string proxyUrl            = UrlUtil.ConstructProxyTicketRequestUrl(casTicket.ProxyGrantingTicket, url.AbsoluteUri);

                string ticket;
                try
                {
                    ticket = CasAuthentication.GetProxyTicketIdFor(url.AbsoluteUri);
                }
                catch (InvalidOperationException ioe)
                {
                    ticket = "Invalid Request: " + ioe.Message;
                }
                catch (TicketValidationException tve)
                {
                    ticket = "Ticket Exception: " + tve.Message;
                }

                string clickOnceValidation = validateUrl + "?service=" + Server.UrlEncode(url.AbsoluteUri) + "&proxyTicket=" + ticket;
                string appUrl = new UriBuilder(Request.Url.Scheme, Request.Url.DnsSafeHost, Request.Url.Port, ResolveUrl("DotNetCasProxyDemoApp.application"), "?proxyTicket=" + ticket + "&verifyUrl=" + Server.UrlEncode(validateUrl)).Uri.AbsoluteUri;

                StringBuilder debugText = new StringBuilder();
                debugText.AppendLine("Your PGT");
                debugText.AppendLine(proxyGrantingTicket);
                debugText.AppendLine();

                debugText.AppendLine("Target Service URL");
                debugText.AppendLine(url.AbsoluteUri);
                debugText.AppendLine();

                debugText.AppendLine("Proxy Ticket URL");
                debugText.AppendLine(proxyUrl);
                debugText.AppendLine();

                debugText.AppendLine("Proxy Ticket");
                debugText.AppendLine(ticket);
                debugText.AppendLine();

                debugText.AppendLine("Validate URL");
                debugText.AppendLine(validateUrl);
                debugText.AppendLine();

                debugText.AppendLine("ClickOnce URL");
                debugText.AppendLine(appUrl);
                debugText.AppendLine();

                debugText.AppendLine("ClickOnce Validation");
                debugText.AppendLine(clickOnceValidation);

                DebugField.Text   = debugText.ToString();
                ClickOnceUrl.Text = appUrl;
            }
        }
예제 #25
0
        /// <summary>
        /// 走,登录去。。。
        /// </summary>
        /// <returns></returns>
        public ActionResult GoToLogin()
        {
            if ("1".Equals(IsOpenSxLogin))
            {
                if (User.Identity.IsAuthenticated)
                {
                    string userAccount = CasAuthentication.CurrentPrincipal.Identity.Name;
                    using (ClientSiteClientProxy proxy = new ClientSiteClientProxy(ProxyEx(Request, userAccount)))
                    {
                        Result <UserView> loginResult = proxy.LoginByCas(userAccount);
                        if (loginResult.Flag == 0)
                        {
                            Session[ConstStr_Session.CurrentUserEntity] = loginResult.Data;

                            LoadUserRight(loginResult.Data.RoleType.ToString(), loginResult.Data.UserId);

                            Result <List <Base_Right> > result = proxy.LoadRightList(loginResult.Data.RoleType.ToString(), loginResult.Data.UserId);
                            if (result.Flag == EResultFlag.Success)
                            {
                                var list = result.Data.Where(i => i.ParentId == 0 && i.IsMenu).ToList();

                                List <WebRightNode> rightNodesList = list.Select(p => new WebRightNode()
                                {
                                    Id     = p.Id,
                                    Name   = p.DisplayName,
                                    Url    = p.URL,
                                    Target = p.Target
                                }).ToList();

                                foreach (var rightNode in rightNodesList)
                                {
                                    rightNode.ChildNode = GetChildNode(rightNode.Id, result.Data);
                                }

                                Session[ConstStr_Session.CurrUserRight] = rightNodesList;
                                ClientProxyExType cpet = new ClientProxyExType();
                                cpet              = new ClientProxyExType();
                                cpet.UserID       = loginResult.Data.UserId.ToString();
                                cpet.IP_Client    = Request.UserHostAddress;
                                cpet.IP_WebServer = NetTools.GetLocalMachineIP4();
                                cpet.CurrentUser  = loginResult.Data;
                                Session[ConstStr_Session.CurrentProxyExType] = cpet;
                            }
                        }
                    }

                    string url = "Home/SignIndex";
                    if (Request.QueryString.AllKeys.Contains("returnUrl"))
                    {
                        url = Request.QueryString["returnUrl"];
                    }
                    return(Redirect(url));
                }
                else
                {
                    CasAuthentication.RedirectToLoginPage();
                    Response.Write("你不登录?");
                    Response.End();
                }
            }
            else
            {
                return(RedirectToAction("Login"));
            }
            return(View());
        }
예제 #26
0
        protected void OutstandingTickets_RowCommand(object sender, GridViewCommandEventArgs e)
        {
            int    index  = int.Parse(e.CommandArgument.ToString());
            string ticket = null;

            if (OutstandingTickets != null && OutstandingTickets.DataKeys != null && OutstandingTickets.DataKeys[index] != null)
            {
                ticket = (OutstandingTickets.DataKeys[index].Values["ServiceTicket"].ToString());
            }

            bool isMyTicket = false;
            IEnumerable <string> allMyTickets = CasAuthentication.ServiceTicketManager.GetUserServiceTickets(HttpContext.Current.User.Identity.Name);

            foreach (string myTicket in allMyTickets)
            {
                if (myTicket == ticket)
                {
                    isMyTicket = true;
                    break;
                }
            }

            if (e.CommandName == "Revoke")
            {
                CasAuthentication.ServiceTicketManager.RevokeTicket(ticket);
                if (isMyTicket)
                {
                    CasAuthentication.ClearAuthCookie();
                }
                Page.Response.Redirect(Request.RawUrl, false);
            }
            else if (e.CommandName == "SSO")
            {
                string samlString =
                    @"<samlp:LogoutRequest ID=""" + new Random().Next(10000) + @""" Version=""2.0"" IssueInstant=""" + DateTime.Now + @""">" +
                    @"<saml:NameID>@NOT_USED@</saml:NameID>" +
                    @"<samlp:SessionIndex>" + ticket + "</samlp:SessionIndex>" +
                    @"</samlp:LogoutRequest>";

                string request = "logoutRequest=" + Server.UrlEncode(samlString);

                HttpWebRequest req = (HttpWebRequest)WebRequest.Create(Page.Request.Url.ToString());
                req.Method        = "POST";
                req.ContentType   = "application/x-www-form-urlencoded";
                req.ContentLength = request.Length;
                using (Stream requestStream = req.GetRequestStream())
                {
                    using (StreamWriter requestStreamWriter = new StreamWriter(requestStream))
                    {
                        requestStreamWriter.Write(request);
                    }
                }

                HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
                using (Stream responseStream = resp.GetResponseStream())
                {
                    using (StreamReader responseStreamReader = new StreamReader(responseStream))
                    {
                        string responseBody = responseStreamReader.ReadToEnd();
                        ResponseField.Text = responseBody;
                    }
                }

                Response.Redirect(Request.RawUrl);
            }
        }
예제 #27
0
 /// <summary>
 /// Logs the user off (from CAS).  As of now, this will take you to the CAS logout page by default.
 /// </summary>
 /// <returns></returns>
 public ActionResult LogOff()
 {
     CasAuthentication.SingleSignOut();
     return(RedirectToAction("Index", "Home"));
 }
예제 #28
0
 /// <summary>
 /// Empty constructor (to be used during Serialization/Deserialization)
 /// </summary>
 private CasAuthenticationTicket()
 {
     CasAuthentication.Initialize();
     Proxies = new List <string>();
 }