googleaccountsservice.java

来自「CAS在Tomcat中实现单点登录项目,单点登录(Single Sign On 」· Java 代码 · 共 261 行

JAVA
261
字号
/* * Copyright 2007 The JA-SIG Collaborative. All rights reserved. See license * distributed with this file and available online at * http://www.uportal.org/license.html */package org.jasig.cas.authentication.principal;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.UnsupportedEncodingException;import java.security.PrivateKey;import java.security.PublicKey;import java.util.Calendar;import java.util.Date;import java.util.HashMap;import java.util.Map;import java.util.Random;import java.util.zip.DataFormatException;import java.util.zip.Inflater;import java.util.zip.InflaterInputStream;import javax.servlet.http.HttpServletRequest;import org.jasig.cas.util.SamlUtils;import org.jdom.Document;import org.springframework.util.StringUtils;import org.springframework.webflow.util.Base64;/** * Implementation of a Service that supports Google Accounts (eventually a more * generic SAML2 support will come). *  * @author Scott Battaglia * @version $Revision: 1.1 $ $Date: 2005/08/19 18:27:17 $ * @since 3.1 */public class GoogleAccountsService extends AbstractWebApplicationService {    /**     * Comment for <code>serialVersionUID</code>     */    private static final long serialVersionUID = 6678711809842282833L;    private static Random random = new Random();        private static final char[] charMapping = {      'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',      'p'};    private static final String CONST_PARAM_SERVICE = "SAMLRequest";    private static final String CONST_RELAY_STATE = "RelayState";    private static final String TEMPLATE_SAML_RESPONSE = "<samlp:Response ID=\"<RESPONSE_ID>\" IssueInstant=\"<ISSUE_INSTANT>\" Version=\"2.0\""        + " xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\""        + " xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\""        + " xmlns:xenc=\"http://www.w3.org/2001/04/xmlenc#\">"        + "<samlp:Status>"        + "<samlp:StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\" />"        + "</samlp:Status>"        + "<Assertion ID=\"<ASSERTION_ID>\""        + " IssueInstant=\"2003-04-17T00:46:02Z\" Version=\"2.0\""        + " xmlns=\"urn:oasis:names:tc:SAML:2.0:assertion\">"        + "<Issuer>https://www.opensaml.org/IDP</Issuer>"        + "<Subject>"        + "<NameID Format=\"urn:oasis:names:tc:SAML:2.0:nameid-format:emailAddress\">"        + "<USERNAME_STRING>"        + "</NameID>"        + "<SubjectConfirmation Method=\"urn:oasis:names:tc:SAML:2.0:cm:bearer\"/>"        + "</Subject>"        + "<Conditions NotBefore=\"2003-04-17T00:46:02Z\""        + " NotOnOrAfter=\"<NOT_ON_OR_AFTER>\">"        + "</Conditions>"        + "<AuthnStatement AuthnInstant=\"<AUTHN_INSTANT>\">"        + "<AuthnContext>"        + "<AuthnContextClassRef>"        + "urn:oasis:names:tc:SAML:2.0:ac:classes:Password"        + "</AuthnContextClassRef>"        + "</AuthnContext>"        + "</AuthnStatement>"        + "</Assertion></samlp:Response>";    private final String relayState;    private final PublicKey publicKey;    private final PrivateKey privateKey;    protected GoogleAccountsService(final String id, final String relayState,        final PrivateKey privateKey, final PublicKey publicKey) {        this(id, id, null, relayState, privateKey, publicKey);    }    protected GoogleAccountsService(final String id, final String originalUrl,        final String artifactId, final String relayState,        final PrivateKey privateKey, final PublicKey publicKey) {        super(id, originalUrl, artifactId);        this.relayState = relayState;        this.privateKey = privateKey;        this.publicKey = publicKey;    }    public static GoogleAccountsService createServiceFrom(        final HttpServletRequest request, final PrivateKey privateKey,        final PublicKey publicKey) {        final String relayState = request.getParameter(CONST_RELAY_STATE);        final String xmlRequest = decodeAuthnRequestXML(request            .getParameter(CONST_PARAM_SERVICE));        if (!StringUtils.hasText(xmlRequest)) {            return null;        }        final Document document = SamlUtils            .constructDocumentFromXmlString(xmlRequest);        if (document == null) {            return null;        }        final String assertionConsumerServiceUrl = document.getRootElement().getAttribute("AssertionConsumerServiceURL").getValue();        return new GoogleAccountsService(assertionConsumerServiceUrl,            relayState, privateKey, publicKey);    }    public Response getResponse(final String ticketId) {        final Map<String, String> parameters = new HashMap<String, String>();        final String samlResponse = constructSamlResponse();        final String signedResponse = SamlUtils.signSamlResponse(samlResponse,            this.privateKey, this.publicKey);        parameters.put("SAMLResponse", signedResponse);        parameters.put("RelayState", this.relayState);        return Response.getPostResponse(getOriginalUrl(), parameters);    }    /**     * Service does not support Single Log Out     *      * @see org.jasig.cas.authentication.principal.WebApplicationService#logOutOfService(java.lang.String)     */    public boolean logOutOfService(final String sessionIdentifier) {        return false;    }    private String constructSamlResponse() {        String samlResponse = TEMPLATE_SAML_RESPONSE;        final Calendar c = Calendar.getInstance();        c.setTime(new Date());        c.add(Calendar.YEAR, 1);                samlResponse = samlResponse.replace("<USERNAME_STRING>", getPrincipal()            .getId());        samlResponse = samlResponse.replace("<RESPONSE_ID>", createID());        samlResponse = samlResponse.replace("<ISSUE_INSTANT>", SamlUtils            .getCurrentDateAndTime());        samlResponse = samlResponse.replace("<AUTHN_INSTANT>", SamlUtils            .getCurrentDateAndTime());        samlResponse = samlResponse.replace("<NOT_ON_OR_AFTER>", SamlUtils            .getFormattedDateAndTime(c.getTime()));        samlResponse = samlResponse.replace("<ASSERTION_ID>", createID());        return samlResponse;    }        private static String createID() {        final byte[] bytes = new byte[20]; // 160 bits        random.nextBytes(bytes);        final char[] chars = new char[40];        for (int i = 0; i < bytes.length; i++) {          int left = (bytes[i] >> 4) & 0x0f;          int right = bytes[i] & 0x0f;          chars[i * 2] = charMapping[left];          chars[i * 2 + 1] = charMapping[right];        }        return String.valueOf(chars);      }    private static String decodeAuthnRequestXML(        final String encodedRequestXmlString) {        if (encodedRequestXmlString == null) {            return null;        }        final byte[] decodedBytes = base64Decode(encodedRequestXmlString);        if (decodedBytes == null) {            return null;        }        final String inflated = inflate(decodedBytes);        if (inflated != null) {            return inflated;        }        return zlibDeflate(decodedBytes);    }    private static String zlibDeflate(final byte[] bytes) {        final ByteArrayInputStream bais = new ByteArrayInputStream(bytes);        final ByteArrayOutputStream baos = new ByteArrayOutputStream();        final InflaterInputStream iis = new InflaterInputStream(bais);        final byte[] buf = new byte[1024];        try {            int count = iis.read(buf);            while (count != -1) {                baos.write(buf, 0, count);                count = iis.read(buf);            }            return new String(baos.toByteArray());        } catch (final Exception e) {            return null;        } finally {            try {                iis.close();            } catch (final Exception e) {                // nothing to do            }        }    }    private static byte[] base64Decode(final String xml) {        try {            final Base64 base64Decoder = new Base64();            final byte[] xmlBytes = xml.getBytes("UTF-8");            return base64Decoder.decode(xmlBytes);        } catch (final Exception e) {            return null;        }    }    private static String inflate(final byte[] bytes) {        final Inflater inflater = new Inflater(true);        final byte[] xmlMessageBytes = new byte[5000];        inflater.setInput(bytes);        try {            final int resultLength = inflater.inflate(xmlMessageBytes);            if (!inflater.finished()) {                throw new RuntimeException("buffer not large enough.");            }            inflater.end();            return new String(xmlMessageBytes, 0, resultLength, "UTF-8");        } catch (final DataFormatException e) {            return null;        } catch (final UnsupportedEncodingException e) {            throw new RuntimeException("Cannot find encoding: UTF-8", e);        }    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?