单点登录cas Java篇

基于服务端的修改流程:客户端所有的远程请求都必须携带有loginUrl参数信息以使得服务器端知道在认证失败后转向客户端登陆页面。

    我们首先需要重新实现一个自己的认证过滤器,以下是我们自己的认证过滤器的代码:

 

/**

 * 远程认证过滤器.

 * 由于AuthenticationFilter的doFilter方法被声明为final,

 * 只好重新实现一个认证过滤器,支持localLoginUrl设置.

 *

 */

public class RemoteAuthenticationFilter extendsAbstractCasFilter {

   

    public static finalString CONST_CAS_GATEWAY = "_const_cas_gateway_";

 

    /**

     * 本地登陆页面URL.

     */

    privateString localLoginUrl;

   

    /**

     * The URL to the CASServer login.

     */

    private StringcasServerLoginUrl;

 

    /**

     * Whether to send therenew request or not.

     */

    private boolean renew= false;

 

    /**

     * Whether to send thegateway request or not.

     */

    private booleangateway = false;

 

    protected voidinitInternal(final FilterConfig filterConfig) throws ServletException {

       super.initInternal(filterConfig);

        setCasServerLoginUrl(getPropertyFromInitParams(filterConfig,"casServerLoginUrl", null));

       log.trace("Loaded CasServerLoginUrl parameter: " +this.casServerLoginUrl);

       setLocalLoginUrl(getPropertyFromInitParams(filterConfig,"localLoginUrl", null));

        log.trace("Loaded LocalLoginUrlparameter: " + this.localLoginUrl);

       setRenew(Boolean.parseBoolean(getPropertyFromInitParams(filterConfig,"renew", "false")));

       log.trace("Loaded renew parameter: " + this.renew);

        setGateway(Boolean.parseBoolean(getPropertyFromInitParams(filterConfig,"gateway", "false")));

       log.trace("Loaded gateway parameter: " + this.gateway);

    }

 

    public void init() {

        super.init();

       CommonUtils.assertNotNull(this.localLoginUrl, "localLoginUrl cannotbe null.");

       CommonUtils.assertNotNull(this.casServerLoginUrl,"casServerLoginUrl cannot be null.");

    }

 

    public final voiddoFilter(final ServletRequest servletRequest,

            finalServletResponse servletResponse, final FilterChain filterChain)

            throwsIOException, ServletException {

        finalHttpServletRequest request = (HttpServletRequest) servletRequest;

        finalHttpServletResponse response = (HttpServletResponse) servletResponse;

        final HttpSessionsession = request.getSession(false);

        final Stringticket = request.getParameter(getArtifactParameterName());

        final Assertionassertion = session != null ? (Assertion) session

               .getAttribute(CONST_CAS_ASSERTION) : null;

        final booleanwasGatewayed = session != null

                &&session.getAttribute(CONST_CAS_GATEWAY) != null;

 

        // 如果访问路径为localLoginUrl且带有validated参数则跳过

        URL url = newURL(localLoginUrl);

        final booleanisValidatedLocalLoginUrl = request.getRequestURI().endsWith(url.getPath())&&

           CommonUtils.isNotBlank(request.getParameter("validated"));

       

        if(!isValidatedLocalLoginUrl && CommonUtils.isBlank(ticket) &&assertion == null && !wasGatewayed) {

           log.debug("no ticket and no assertion found");

            if(this.gateway) {

               log.debug("setting gateway attribute in session");

               request.getSession(true).setAttribute(CONST_CAS_GATEWAY,"yes");

            }

 

            final StringserviceUrl = constructServiceUrl(request, response);

 

            if(log.isDebugEnabled()) {

               log.debug("Constructed service url: " + serviceUrl);

            }

 

            StringurlToRedirectTo = CommonUtils.constructRedirectUrl(

                   this.casServerLoginUrl, getServiceParameterName(),

                   serviceUrl, this.renew, this.gateway);

 

            // 加入localLoginUrl

            urlToRedirectTo+= (urlToRedirectTo.contains("?") ? "&" :"?") + "loginUrl=" + URLEncoder.encode(localLoginUrl,"utf-

8");

 

            if(log.isDebugEnabled()) {

               log.debug("redirecting to \"" + urlToRedirectTo +"\"");

            }

           

            response.sendRedirect(urlToRedirectTo);

            return;

        }

 

        if (session !=null) {

           log.debug("removing gateway attribute from session");

           session.setAttribute(CONST_CAS_GATEWAY, null);

        }

 

       filterChain.doFilter(request, response);

    }

 

    public final voidsetRenew(final boolean renew) {

        this.renew =renew;

    }

 

    public final voidsetGateway(final boolean gateway) {

        this.gateway =gateway;

    }

 

    public final voidsetCasServerLoginUrl(final String casServerLoginUrl) {

       this.casServerLoginUrl = casServerLoginUrl;

    }

 

    public final voidsetLocalLoginUrl(String localLoginUrl) {

        this.localLoginUrl= localLoginUrl;

    }

   

}

 

    代码均拷贝自org.jasig.cas.client.authentication.AuthenticationFilter,并进行修改,可以看到我们为原有的认证过滤器增加了一个参数localLoginUrl。在WEB-INF/web.xml中配置:

 

<filter>

    <filter-name>CASAuthentication Filter</filter-name>

   <filter-class>com.baidu.cas.client.validation.RemoteAuthenticationFilter</filter-class>

    <init-param>

       <param-name>localLoginUrl</param-name>

<param-value>http://client/login.jsp</param-value>//客户端未登录时转向页面

   </init-param>

    <init-param>

       <param-name>casServerLoginUrl</param-name>

       <param-value>https://server/remoteLogin</param-value>//服务端的验证地址,其中remoteLogin在服务端有配置

    </init-param>

    <init-param>

        <param-name>serverName</param-name>

       <param-value>http://client </param-value>

    </init-param>

</filter>

<filter-mapping>

    <filter-name>CASAuthentication Filter</filter-name>

   <url-pattern>/*</url-pattern>

</filter-mapping>

 

此处我们将过滤器指向自己的过滤器并增加本地登陆页面路径设置。最后我们来看看登陆页面login.jsp:

 

<%@ page language="java"contentType="text/html; charset=utf-8"pageEncoding="utf-8"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<head>

    <metahttp-equiv="Content-Type" content="text/html;charset=utf-8">

    <title>远程CAS客户端登陆页面</title>

    <linkrel="stylesheet" type="text/css" href="<%=request.getContextPath() %>/styles/main.css" />

    <scripttype="text/javascript">

    functiongetParam(name) {

        var queryString =window.location.search;

        var param =queryString.substr(1, query.length - 1).split("&");

        for (var i = 0; i< param.length; i++) {

            var keyValue =param[i].split("=");

            if(keyValue[0] == name) return keyValue[1];

        }

        return null;

    }

    function init() {

        // 显示异常信息

        var error =getParam("errorMessage");

        if (error) {

           document.getElementById("errorMessage").innerHTML =decodeURIComponent(error);

        }

        // 注入service

        var service =getParam("service");

        if (service)

           document.getElementById("service").value =decodeURIComponent(service);

        else

           document.getElementById("service").value = location.href;

    }

    </script>

</head>

<body>

    <h1>远程CAS客户端登陆页面</h1>

    <% if(request.getRemoteUser() == null) { %>

        <divid="errorMessage"></div>

        <formid="myLoginForm" action="https://server/remoteLogin"method="post">

            <inputtype="hidden" id="service" name="service"value="">

            <inputtype="hidden" name="loginUrl" value="http://client /login.jsp">

            <inputtype="hidden" name="submit" value="true" />

            <table>

                <tr>

                    <td>用户名:</td>

                   <td><input type="text"name="username"></td>

               </tr>

                <tr>

                   <td>密&nbsp;&nbsp;码:</td>

                   <td><input type="password"name="password"></td>

                </tr>

                <tr>

                    <tdcolspan="2"><input type="submit" value="登陆" /></td>

               </tr>

            </table>

        </form>

        <scripttype="text/javascript">init()</script>

    <% } else { %>

        <div class="welcome">您好:<%= request.getRemoteUser()%></div>

        <divid="logout">

            <ahref="https:// server/remoteLogout?service=http://client /login.jsp">单点

登出</a>

        </div>

    <% } %>

</body>

</html>

 

login.jsp为了简单起见,仅有是否已登陆判断使用了服务器端代码,其他均使用客户端代码实现。

我们首先将表单action指向服务器端remoteLogin,然后在里面设置了两个重要的hidden域以传递 loginUrl和submit参数,前者

用于告诉服务器失败后转向何处,后者告诉服务器端webflow现在要进行提交而不是TGT认证请求

 

 

http://localhost:3449/Admin/WebAPI/loginOSS.aspx


你可能感兴趣的:(java,session,服务器,service,null,stylesheet)