简体   繁体   中英

JASIG CAS Login without CAS login screen

We are trying to use CAS server for SSO for our existing web based applications. Our goals are

  • Achive SSO across the various applications (including cross domain).
  • Have Customized login (In UI Terms) pages for different apps, when they are redirected to CAS Server login page.
  • Ability to do login without going to the CAS Login page, reason being "A small login section" is embedded in the page itself and user will not be redirected to the CAS login page for better usability.

We are done with the first and second goal. But having problems with third one.

For this functionality we are trying to replicate the same actions as in second goal , only difference being submitting/posting the data (credentials , login tickets etc) from non CAS login page.

  • We cannot use iframes to show the CAS login page in the small section , this is vulnerable to browser compatability issues.
  • We cannot use ajax to use CAS api's to getting the login ticket and doing the HTTP post (cross domain issue)
  • What we have done is : Retrieve the loginticket and execution id on the load of the non cas login page by doing an HTTP post on the server side. when we post the username / password along with the loginticket and execId , the CAS server instead of accepting the post data redirects the user to CAS login page but doing a browser back and submitting the data again works fine. Reasons is no jsession extablished between the CAS and the browser and hence CAS rejects any post data. We can use the CAS restAPI but it will just login the user and no help in getting the SSO done.

Any thoughts on how can we handle this problem ??

Thanks, Pratik

There is a wiki page on CAS which debates about that : https://wiki.jasig.org/display/CAS/Using+CAS+without+the+Login+Screen (but which is older than the google groups discussion proposed by Misagh M ).

My solution is " Using CAS from external link or custom external form ".

I know its late but if someone is looking for an answer this is how I solve this. This is the code I put in casLoginView.jsp

<head>
    <script language="javascript">
        function doAutoLogin() {
            document.forms[0].submit();
        }
    </script>
</head>
<body onload="doAutoLogin();">
    <form id="credentials" method="POST" action="<%= request.getContextPath() %>/login?service=<%= request.getParameter("service") %>">
        <input type="hidden" name="lt" value="${loginTicket}" />
        <input type="hidden" name="execution" value="${flowExecutionKey}" />
        <input type="hidden" name="_eventId" value="submit" />
        <input type="hidden" name="serviceLogin" value="<%= request.getParameter("serviceLogin") %>"/>
        <input type="hidden" name="username" value="<%= request.getParameter("username") %>" />
        <input type="hidden" name="password" value="<%= request.getParameter("password") %>" />
        <% 
        if ("true".equals(request.getParameter("rememberMe"))) {%>
            <input type="hidden" name="rememberMe" id="rememberMe" value="true"/>
        <% } %>

        <input type="submit" value="Submit" style="visibility: hidden;" />
    </form>
    <% } else {
        response.sendRedirect(request.getParameter("redirectURL"));
       }
    %>
</body>

And in your webapp just make a POST petition to your CAS server.

Hope it helps

  1. You must get a copy of CAS official client source code( cas-client-core, https://github.com/apereo/java-cas-client ), and make sure you could compile it.

  2. You need change the doFilter() function code at org.jasig.cas.client.authentication.AuthenticationFilter in client source code like the below.

     final HttpServletRequest request = (HttpServletRequest) servletRequest; final HttpServletResponse response = (HttpServletResponse) servletResponse; final HttpSession session = request.getSession(false); final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null; if(request.getServletPath().toLowerCase().equals("/caslogout.jsp")) { // Set the custom client login page when you logout from CAS server. request.setAttribute("casServerLogoutUrl",casServerLoginUrl.replace("login","logout")); request.setAttribute("customServerLoginUrl",customServerLoginUrl); //We must remove the attribute of CONST_CAS_ASSERTION manually if(session!=null) session.removeAttribute(CONST_CAS_ASSERTION); filterChain.doFilter(request, response); return; } if (assertion != null) { filterChain.doFilter(request, response); return; } // Although the custom login page must called caslogin, here you can change it. if(request.getServletPath().toLowerCase().equals("/caslogin.jsp")) { //Set the a default parameter to the caslogin request.setAttribute("defaultServerIndexUrl",defaultServerIndexUrl); request.setAttribute("casServerLoginUrl",casServerLoginUrl); filterChain.doFilter(request, response); return; } final String serviceUrl = constructServiceUrl(request, response); final String ticket = CommonUtils.safeGetParameter(request,getArtifactParameterName()); final boolean wasGatewayed = this.gatewayStorage.hasGatewayedAlready(request, serviceUrl); if (CommonUtils.isNotBlank(ticket) || wasGatewayed) { filterChain.doFilter(request, response); return; } final String modifiedServiceUrl; log.debug("no ticket and no assertion found"); if (this.gateway) { log.debug("setting gateway attribute in session"); modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl); } else { modifiedServiceUrl = serviceUrl; } if (log.isDebugEnabled()) { log.debug("Constructed service url: " + modifiedServiceUrl); } final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway); if (log.isDebugEnabled()) { log.debug("redirecting to \"" + urlToRedirectTo + "\""); } // Add a custom server login url parameter to the CAS login url. response.sendRedirect(urlToRedirectTo+"&customLogin=custom&customLoginPage="+customServerLoginUrl);
  3. Add your own compiled cas-client-core to the dependence of your client webapp.

  4. Add the caslogin.jsp to your client webapp.

 <form method="GET" action="<%=request.getAttribute("casServerLoginUrl")%>"> <p>Username : <input type="text" name="username" /></p> <p>Password : <input type="password" name="password" /></p> <p><input type="submit" value="Login" /></p> <input type="hidden" name="auto" value="true" /> <input type="hidden" name="service" value="<%=request.getParameter("service")==null?request.getAttribute("defaultServerIndexUrl"):request.getParameter("service")%>" />

  1. Edit the web.xml in client webapp. Add below code in the filter of CASFilter

 <init-param> <param-name>defaultServerIndexUrl</param-name> <param-value>http://clientip:port/webappname/index.jsp</param-value> </init-param> <init-param> <param-name>customServerLoginUrl</param-name> <param-value>http://clientip:port/webappname/caslogin.jsp</param-value> </init-param>

  1. Edit the code at cas-server-webapp/WEB-INF/view/jsp/default/ui/casLoginView.jsp in CAS server web app.

 <% String auto=request.getParameter("auto"); String customLogin=request.getParameter("customLogin"); if(auto!=null&&auto.equals("true")) { %> <html> <head> <script language="javascript"> function doAutoLogin() { document.forms[0].submit(); } </script> </head> <body onload="doAutoLogin()"> <form id="credentials" method="POST" action="<%=request.getContextPath()%>/login?service=<%=request.getParameter("service")%>"> <input type="hidden" name="lt" value="${loginTicket}" /> <input type="hidden" name="execution" value="${flowExecutionKey}" /> <input type="hidden" name="_eventId" value="submit" /> <input type="hidden" name="username" value="<%=request.getParameter("username")%>" /> <input type="hidden" name="password" value="<%=request.getParameter("password")%>" /> <input type="hidden" name="login_form" value="<%=request.getParameter("login_form")%>" /> <input type="hidden" name="rememberMe" value="true" /> <input type="submit" value="Submit" style="visibility: hidden" /> </form> </body> </html> <% } else if(customLogin!=null&&customLogin.equals("custom")) { response.sendRedirect(request.getParameter("customLoginPage")+"?service="+request.getParameter("service")); %> <% } else {%> <!-- The Orgin Source Code of casLoginView.jsp!!!!!!!!!!!!!!!!!!!!!!!!! --> <%}%>

  1. MAKE SURE you could login cas with caslogin.jsp.
  2. Put the content of your own login page to the caslogin.jsp.
  3. Now you could login cas with your own caslogin.jsp

I also make a sample about how to login cas with client custom login screen rather than server login srceen. You could download it on
https://github.com/yangminxing/cas-custom-login-page

to login cas without login screen page, I custom flow login (write another action-state)

1.In login-webflow.xml you write other action-state of transition in action-state id="generateLoginTicket". In this action-state (I call it is submitNotUseForm), I do the same "realSubmit" action-state.

2.In evaluate of "submitNotUseForm" --> class AuthenticationViaFormAction, I write method submitNotForm() and check :

2.1: if have no service call, it return value for call to "viewLoginForm" else I get parameter from request set for credentials

2.2: Everything else do the same method submit

It work for me !

we tried to hit CAS and add &gateway=true in the URL param. CAS will redirect to our app's base_url/j_spring_cas_security_check without showing login prompt (our app used Spring with CAS)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM