Net有道

紫冠道人的求道历程

导航

CAS的service参数验证

CAS登录成功后会跳转到service参数提供的url,目前系统中这个参数是没有任何验证的,service参数随便赋一个网址就可以。为安全起见现在对这个service要作一下限制,比如只能是同源url才可以重定向。

下面是基于CAS 3.5.2对系统的改造过程。

系统比较老旧,之前也作过CAS方面的改造,基本思路是从login-webflow.xml中找到切入点,查看源代码,然后在配置文件中把相关的bean替换掉。具体分析过程这里不再赘述。

在argumentExtractorsConfiguration.xml中有

 <util:list id="argumentExtractors">
    <ref bean="casArgumentExtractor" />
    <ref bean="samlArgumentExtractor" />
 </util:list>

把casArgumentExtractor替换成customArgumentExtractor。上面那个配置文件里再加上

<bean id="customArgumentExtractor"
   class="org.jasig.cas.web.support.CustomArgumentExtractor"
     p:httpClient-ref="noRedirectHttpClient"
     p:disableSingleSignOut="${slo.callbacks.disabled:false}" />

这个customArgumentExtractor就是要自己新写的。代码很简单,里面只有一个方法

public final class CustomArgumentExtractor extends AbstractSingleSignOutEnabledArgumentExtractor{

    public WebApplicationService extractServiceInternal(HttpServletRequest request) {
        return CustomWebApplicationServiceImpl.createServiceFrom(request,getHttpClientIfSingleSignOutEnabled());
    }
}

CustomWebApplicationServiceImpl也是要自己写的,基于cas-server-core-3.5.2.jar里的SimpleWebApplicationServiceImpl上修改。

在里面的createServiceFrom方法加上验证即可

    public static CustomWebApplicationServiceImpl createServiceFrom(
            final HttpServletRequest request, final HttpClient httpClient)  {
        final String targetService = request
                .getParameter(CONST_PARAM_TARGET_SERVICE);
        final String method = request.getParameter(CONST_PARAM_METHOD);
        final String serviceToUse = StringUtils.hasText(targetService)
                ? targetService : request.getParameter(CONST_PARAM_SERVICE);

        if (!StringUtils.hasText(serviceToUse)) {
            return null;
        }

        //新加的service同host验证---------------
        try {
            URI url = new URI(serviceToUse);
            if (!host.equals(url.getHost())){ 
                return null;
            }
        } catch (URISyntaxException e) {
            return null;
        }
        //---------------验证结束

        final String id = cleanupUrl(serviceToUse);
        final String artifactId = request.getParameter(CONST_PARAM_TICKET);

        return new CustomWebApplicationServiceImpl(id, serviceToUse,
                artifactId, "POST".equals(method) ? Response.ResponseType.POST
                : Response.ResponseType.REDIRECT, httpClient);
    }

上面的host是配置文件里读的当前系统的域名。这里可以加自己的其他验证逻辑,比如二级子目录、通配符域名或者白名单列表。

 

最后还要修改一个地方,在uniqueIdGenerators.xml里

    <util:map id="uniqueIdGeneratorsMap">
        <entry
            key="org.jasig.cas.authentication.principal.SimpleWebApplicationServiceImpl"
            value-ref="serviceTicketUniqueIdGenerator" />
        <entry
            key="org.jasig.cas.support.openid.authentication.principal.OpenIdService"
            value-ref="serviceTicketUniqueIdGenerator" />
......

把SimpleWebApplicationServiceImpl换成CustomWebApplicationServiceImpl。

 

这样修改之后,当service参数的url跟你配置的域名不一致时,等同于service为null,即未配置。在我的系统里会跳转到一个只是简单提示登录成功的jsp页面。

 

posted on 2023-04-23 14:15  lichdr  阅读(338)  评论(0编辑  收藏  举报