代理模式访问过程

分两步实现代理过程:
1、用户先访问CAS单点登录代理端(也就是上一章节中客户端1)的地址
url1:http:// localhost:8088/cas-client/test,此地址就是用于普通的单点登录。
2、再访问CAS单点登录代理端地址
url2:http:// localhost:8088/cas-client/proxyServlet
在上一章节中我们知道在url的请求下到servlet中要访问被代理端(也就是上一章节客户端2)的接口: http:// localhost:8087/cas-client-be-used-to-proxy/test

1. 代理端获取用户身份信息之调用ticketValidator.validate

前面章节所总结的客户端过滤器
CAS单点登录客户端向CAS单点登录服务端发送验证请求,与普通模式比较,在“调用第3个filter”之前一样,在此不赘述,我们将直接从“调用ticketValidator.validate校验ticket”开始进行代码的分析和解读。

public abstract class AbstractUrlBasedTicketValidator implements TicketValidator {
    public final Assertion validate(final String ticket, final String service) throws TicketValidationException {
        final String validationUrl = constructValidationUrl(ticket, service);
        logger.debug("Constructing validation url: {}", validationUrl);

        try {
            logger.debug("Retrieving response from server.");
            final String serverResponse = retrieveResponseFromServer(new URL(validationUrl), ticket);
           ......

调用constructValidationUrl()与普通模式比,请求的url会增加pgtUrl=xxx, 调用retrieveResponseFromServer(),与普通模式过程一样,但是请求的URL和普通模式不同。
后面分别分析constructValidationUrl()和retrieveResponseFromServer()
调用url与普通模式不同

2. 代理端获取用户身份信息之调用constructValidationUrl

在ticketValidator.validate里调用constructValidationUrl

*AbstractUrlBasedTicketValidator.java*
public abstract class AbstractUrlBasedTicketValidator implements TicketValidator {
    protected final String constructValidationUrl(final String ticket, final String serviceUrl) {
        final Map<String, String> urlParameters = new HashMap<String, String>();
        logger.debug("Placing URL parameters in map.");
        urlParameters.put("ticket", ticket);
        urlParameters.put("service", serviceUrl);

        if (this.renew) {
            urlParameters.put("renew", "true");
        }

        logger.debug("Calling template URL attribute map.");
        //添加key="pgtUrl",value="http://localhost:8088/cas_client/proxyCallback"
        populateUrlAttributeMap(urlParameters);
        logger.debug("Loading custom parameters from configuration.");
        if (this.customParameters != null) {
            urlParameters.putAll(this.customParameters);
        }
		//值为"serviceValidate"
        final String suffix = getUrlSuffix();
        final StringBuilder buffer = new StringBuilder(urlParameters.size() * 10 + this.casServerUrlPrefix.length()
                + suffix.length() + 1);
        int i = 0;
        buffer.append(this.casServerUrlPrefix);
        if (!this.casServerUrlPrefix.endsWith("/")) {
            buffer.append("/");
        }
        buffer.append(suffix);
		//构建请求url,带上参数
        for (Map.Entry<String, String> entry : urlParameters.entrySet()) {
            final String key = entry.getKey();
            final String value = entry.getValue();

            if (value != null) {
                buffer.append(i++ == 0 ? "?" : "&");
                buffer.append(key);
                buffer.append("=");
                final String encodedValue = encodeUrl(value);
                buffer.append(encodedValue);
            }
        }
        return buffer.toString();
    }

构建成功的url值为:
http:// localhost:8080/cas/serviceValidate?pgtUrl=http%3A%2F%2Flocalhost%3A8088%2Fcas_client%2FproxyCallback&ticket=ST-7-4cq5kQ55wC9SeHOBDdTU-cas01.example.org&service=http%3A%2F%2Flocalhost%3A8088%2Fcas_client%2Ftest%3Bjsessionid%3DBE30CE36139A115A8B28998B54460A9F

下面我们再来看看populateUrlAttributeMap()和getUrlSuffix()的代码

*Cas20ServiceTicketValidator.java*
public class Cas20ServiceTicketValidator extends AbstractCasProtocolUrlBasedTicketValidator {
    protected final void populateUrlAttributeMap(final Map<String, String> urlParameters) {
        urlParameters.put("pgtUrl", this.proxyCallbackUrl);
    }
    protected String getUrlSuffix() {
        return "serviceValidate";
    }

大家一看就能明白。

3. 代理端获取用户身份信息之调用retrieveResponseFromServer访问CAS服务器

前面章节有分析这个代码,大家看一下请求的url和返回结果吧。

*CommonUtils.java*
public final class CommonUtils {
    public static String getResponseFromServer(final URL constructedUrl, final HttpURLConnectionFactory factory, final String encoding) {
        HttpURLConnection conn = null;
        InputStreamReader in = null;
        try {
            conn = factory.buildHttpURLConnection(constructedUrl.openConnection());
            if (CommonUtils.isEmpty(encoding)) {
                in = new InputStreamReader(conn.getInputStream());
            } else {
                in = new InputStreamReader(conn.getInputStream(), encoding);
            }

            final StringBuilder builder = new StringBuilder(255);
            int byteRead;
            while ((byteRead = in.read()) != -1) {
                builder.append((char) byteRead);
            }
            return builder.toString();
        } catch ......
    }

这里代理端的请求地址为:
http:// localhost:8080/cas/serviceValidate?pgtUrl=http%3A%2F%2Flocalhost%3A8088%2Fcas_client%2FproxyCallback&ticket=ST-7-4cq5kQ55wC9SeHOBDdTU-cas01.example.org&service=http%3A%2F%2Flocalhost%3A8088%2Fcas_client%2Ftest%3Bjsessionid%3DBE30CE36139A115A8B28998B54460A9F

CAS单点登录服务端返回值(后面接着分析服务端过程)为:

<cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
    <cas:authenticationSuccess>
        <cas:user>casuser</cas:user>
<cas:proxyGrantingTicket>PGTIOU-3-dnQIfy74cI6NFpOBcggURbUrX1pbhal2hrnKGPZgvIrVXQiXQb-cas01.example.org</cas:proxyGrantingTicket>
    </cas:authenticationSuccess>
</cas:serviceResponse>

到此,在代理模式下,我们从CAS单点登录服务端获取到了用户信息,以及PGTIOU的值,那么后续我们将解析,CAS单点登录服务端是如何在代理模式下工作的。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐