Motivation
...
Code Block |
---|
<?xml version="1.0" encoding="UTF-8"?> <flow xmlns="http://www.springframework.org/schema/webflow" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-1.0.xsd"> |
<start-state idref="provideLoginTicketToRemoteRequestor" />
<action-state id="provideLoginTicketToRemoteRequestor">
<action bean="provideLoginTicketToRemoteRequestorAction" />
<transition on="loginTicketRequested" to="viewRedirectToRequestor" />
<transition on="continue" to="automaticCookiePathSetter" />
</action-state>
<view-state id="viewRedirectToRequestor" view="bmRedirectToRequestorView">
<transition on="submit" to="bindAndValidate" />
</view-state>
Code Block |
---|
<action-state id="automaticCookiePathSetter"> <action bean="automaticCookiePathSetterAction" /> <transition on="success" to="ticketGrantingTicketExistsCheckAction" /> </action-state> <action-state id="ticketGrantingTicketExistsCheckAction"> <action bean="ticketGrantingTicketExistsAction" /> <transition on="ticketGrantingTicketExists" to="hasServiceCheck" /> <transition on="noTicketGrantingTicketExists" to="gatewayRequestCheck" /> </action-state> <action-state id="gatewayRequestCheck"> <action bean="gatewayRequestCheckAction" /> <transition on="gateway" to="redirect" /> <transition on="authenticationRequired" to="viewLoginForm" /> </action-state> <action-state id="hasServiceCheck"> <action bean="hasServiceCheckAction" /> <transition on="authenticatedButNoService" to="viewGenericLoginSuccess" /> <transition on="hasService" to="renewRequestCheck" /> </action-state> <action-state id="renewRequestCheck"> <action bean="renewRequestCheckAction" /> <transition on="authenticationRequired" to="viewLoginForm" /> <transition on="generateServiceTicket" to="generateServiceTicket" /> </action-state> <!-- <action-state id="startAuthenticate"> <action bean="x509Check" /> <transition on="success" to="sendTicketGrantingTicket" /> <transition on="error" to="viewLoginForm" /> </action-state> --> <view-state id="viewLoginForm" view="casLoginView"> <transition on="submit" to="bindAndValidate" /> </view-state> <action-state id="bindAndValidate"> <action bean="authenticationViaFormAction" /> <transition on="success" to="submit" /> <transition on="error" to="viewLoginForm" /> </action-state> <action-state id="submit"> <action bean="authenticationViaFormAction" method="submit" /> <transition on="warn" to="warn" /> <transition on="success" to="sendTicketGrantingTicket" /> <transition on="error" to="viewLoginForm" /> |
<transition on="errorForRemoteRequestor" to="viewRedirectToRequestor" />
Code Block |
---|
</action-state> <action-state id="sendTicketGrantingTicket"> <action bean="sendTicketGrantingTicketAction" /> <transition on="success" to="serviceCheck" /> </action-state> <action-state id="serviceCheck"> <action bean="hasServiceCheckAction" /> <transition on="authenticatedButNoService" to="viewGenericLoginSuccess" /> <transition on="hasService" to="generateServiceTicket" /> </action-state> <action-state id="generateServiceTicket"> <action bean="generateServiceTicketAction" /> <transition on="success" to="warn" /> <transition on="error" to="viewLoginForm" /> <transition on="gateway" to="redirect" /> </action-state> <!-- The "warn" action makes the determination of whether to redirect directly to the requested service or display the "confirmation" page to go back to the server. --> <action-state id="warn"> <action bean="warnAction" /> <transition on="redirect" to="redirect" /> <transition on="warn" to="showWarningView" /> </action-state> <!-- the "viewGenericLogin" is the end state for when a user attempts to login without coming directly from a service. They have only initialized their single-sign on session. --> <end-state id="viewGenericLoginSuccess" view="casLoginGenericSuccessView" /> <!-- The "showWarningView" end state is the end state for when the user has requested privacy settings (to be "warned") to be turned on. It delegates to a view defines in default_views.properties that display the "Please click here to go to the service." message. --> <end-state id="showWarningView" view="casLoginConfirmView" /> <!-- The "redirect" end state allows CAS to properly end the workflow while still redirecting the user back to the service required. --> <end-state id="redirect" view="externalRedirect:${externalContext.requestParameterMap['service']}${requestScope.ticket == null ? '' : (externalContext.requestParameterMap['service'].indexOf('?') != -1 ? '&' : '?') + 'ticket=' + requestScope.ticket}" /> <global-transitions> <transition to="viewServiceErrorView" on-exception="org.jasig.cas.services.UnauthorizedServiceException" /> </global-transitions> </flow> |
...
Code Block |
---|
[...] try { final String ticketGrantingTicketId = this.centralAuthenticationService .createTicketGrantingTicket(credentials); ContextUtils.addAttribute(context, AbstractLoginAction.REQUEST_ATTRIBUTE_TICKET_GRANTING_TICKET, ticketGrantingTicketId); setWarningCookie(response, warn); return success(); } catch (final TicketException e) { populateErrorsInstance(context, e); |
// START: ChangesBusinessMart: check, whether the posting has been sent from a remote server
String myServerName = request.getLocalName();
String referrer = request.getParameter("login-at");
if (referrer != null && referrer.indexOf(myServerName) == -1) {
return result("errorForRemoteRequestor");
}
Code Block |
---|
return error(); } [...] |
...
Code Block |
---|
package de.businessmart.sso.cas.flow; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.jasig.cas.web.flow.util.ContextUtils; import org.springframework.beans.factory.InitializingBean; import org.springframework.webflow.action.AbstractAction; import org.springframework.webflow.core.collection.MutableAttributeMap; import org.springframework.webflow.execution.Event; import org.springframework.webflow.execution.RequestContext; import de.businessmart.sso.cas.CasUtility; /** * Opens up the CAS web flow to allow external retrieval of a login ticket. * @author konrad.wulf * */ public class ProvideLoginTicketToRemoteRequestorAction extends AbstractAction { @Override protected Event doExecute(RequestContext context) throws Exception { final HttpServletRequest request = ContextUtils.getHttpServletRequest(context); if (request.getParameter("get-lt") != null && request.getParameter("get-lt").equalsIgnoreCase("true")) { return result("loginTicketRequested"); } return result("continue"); } } |
viewRedirectToRequestor actually does the redirects to the referrer:
Code Block |
---|
<%@page import="de.businessmart.sso.cas.CasUtility"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <% String separator = ""; String referrer = request.getHeader("Referer"); referrer = CasUtility.resetUrl(referrer); if (referrer != null && referrer.length() > 0) { separator =(referrer.indexOf("?") > -1)? "&" : "?"; %> <html> <head> <script> var redirectURL = "<%= referrer + separator %>lt=${flowExecutionKey}"; <spring:hasBindErrors name="credentials"> redirectURL += '&error_message=' + encodeURIComponent ('<c:forEach var="error" items="${errors.allErrors}"><spring:message code="${error.code}" text="${error.defaultMessage}" /></c:forEach>'); </spring:hasBindErrors> window.location.href = redirectURL; </script> </head> <body></body> </html><% } else { out.print("You better know what to do here."); } %> |
...