import java.io.IOException; import java.util.Vector; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.rpc.Call; import javax.xml.rpc.Service; import javax.xml.rpc.ServiceFactory; import org.apache.axis.message.SOAPBodyElement; import org.apache.xml.serialize.LineSeparator; import org.apache.xml.serialize.OutputFormat; import org.apache.xml.serialize.XMLSerializer; import org.jaxen.JaxenException; import org.jaxen.SimpleNamespaceContext; import org.jaxen.dom.DOMXPath; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Beispiel f�r ein Login-Servlet, das von MOA-ID-AUTH �ber einen Redirect aufgerufen wird. * Es werden demonstriert: * - Parameter�bergabe von MOA-ID-AUTH * - Aufruf des MOA-ID-AUTH Web Service zum Abholen der Anmeldedaten �ber das Apache Axis Framework * - Parsen der Anmeldedaten mittels der XPath Engine "Jaxen" * - Speichern der Anmeldedaten in der HTTPSession * - Redirect auf die eigentliche Startseite der OA * * @author Paul Ivancsics */ public class LoginServletExample extends HttpServlet { // Web Service QName und Endpoint private static final QName SERVICE_QNAME = new QName("GetAuthenticationData"); private static final String ENDPOINT = "http://localhost:8080/moa-id-auth/services/GetAuthenticationData"; // NamespaceContext f�r Jaxen private static SimpleNamespaceContext NS_CONTEXT; static { NS_CONTEXT = new SimpleNamespaceContext(); NS_CONTEXT.addNamespace("saml", "urn:oasis:names:tc:SAML:1.0:assertion"); NS_CONTEXT.addNamespace("samlp", "urn:oasis:names:tc:SAML:1.0:protocol"); NS_CONTEXT.addNamespace("pr", "http://reference.e-government.gv.at/namespace/persondata/20020228#"); } /** * Servlet wird von MOA-ID-AUTH nach erfolgter Authentisierung �ber ein Redirect aufgerufen. */ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // Parameter "Target" und "SAMLArtifact" aus dem Redirect von MOA-ID-AUTH lesen String target = req.getParameter("Target"); String samlArtifact = req.getParameter("SAMLArtifact"); try { // DOMBuilder instanzieren DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); // <samlp:Request> zusammenstellen und in einen DOM-Baum umwandeln String samlRequest = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><samlp:Request IssueInstant=\"2003-01-01T00:00:00+02:00\" MajorVersion=\"1\" MinorVersion=\"0\" RequestID=\"12345678901234567890\" xmlns:samlp=\"urn:oasis:names:tc:SAML:1.0:protocol\"><samlp:AssertionArtifact>" + samlArtifact + "</samlp:AssertionArtifact></samlp:Request>"; Document root_request = builder.parse(new ByteArrayInputStream(samlRequest.getBytes())); // Neues SOAPBodyElement anlegen und mit dem DOM-Baum f�llen SOAPBodyElement body = new SOAPBodyElement(root_request.getDocumentElement()); SOAPBodyElement[] params = new SOAPBodyElement[] { body }; // AXIS-Service f�r Aufruf von MOA-ID-AUTH instanzieren Service service = ServiceFactory.newInstance().createService(SERVICE_QNAME); // Axis-Call erzeugen und mit Endpoint verkn�pfen Call call = service.createCall(); call.setTargetEndpointAddress(ENDPOINT); // Call aufrufen und die Antwort speichern System.out.println("Calling MOA-ID-AUTH ..."); Vector responses = (Vector) call.invoke(params); // erstes BodyElement auslesen SOAPBodyElement response = (SOAPBodyElement) responses.get(0); // <samlp:Response> als DOM-Baum holen Document responseDocument = response.getAsDocument(); Element samlResponse = responseDocument.getDocumentElement(); // <samlp:Response> auf System.out ausgeben System.out.println("Response received:"); OutputFormat format = new OutputFormat((Document) responseDocument); format.setLineSeparator(LineSeparator.Windows); format.setIndenting(true); format.setLineWidth(0); XMLSerializer serializer = new XMLSerializer(System.out, format); serializer.asDOMSerializer(); serializer.serialize(responseDocument); // <samlp:StatusCode> auslesen Attr statusCodeAttr = (Attr)getNode(samlResponse, "/samlp:Response/samlp:Status/samlp:StatusCode/@Value"); String samlStatusCode = statusCodeAttr.getValue(); System.out.println("StatusCode: " + samlStatusCode); // <saml:Assertion> auslesen if ("samlp:Success".equals(samlStatusCode)) { Element samlAssertion = (Element)getNode(samlResponse, "/samlp:Response/saml:Assertion"); // FamilyName aus der <saml:Assertion> parsen Node familyNameNode = getNode(samlAssertion, "//saml:AttributeStatement/saml:Attribute[@AttributeName=\"PersonData\"]/saml:AttributeValue/pr:Person/pr:Name/pr:FamilyName"); String familyName = getText(familyNameNode); System.out.println("Family name: " + familyName); // weitere Anmeldedaten aus der <saml:Assertion> parsen // ... // Anmeldedaten und Target in der HTTPSession speichern HttpSession session = req.getSession(); session.setAttribute("UserFamilyName", familyName); session.setAttribute("Geschaeftsbereich", target); // weitere Anmeldedaten in der HTTPSession speichern // ... // Redirect auf die eigentliche Startseite resp.sendRedirect("/index.jsp"); } } catch (Exception ex) { ex.printStackTrace(); } } /** Returns the first node matching an XPath expression. */ private static Node getNode(Node contextNode, String xpathExpression) throws JaxenException { DOMXPath xpath = new DOMXPath(xpathExpression); xpath.setNamespaceContext(NS_CONTEXT); return (Node) xpath.selectSingleNode(contextNode); } /** Returns the text that a node contains. */ public static String getText(Node node) { if (!node.hasChildNodes()) { return ""; } StringBuffer result = new StringBuffer(); NodeList list = node.getChildNodes(); for (int i = 0; i < list.getLength(); i++) { Node subnode = list.item(i); if (subnode.getNodeType() == Node.TEXT_NODE) { result.append(subnode.getNodeValue()); } else if (subnode.getNodeType() == Node.CDATA_SECTION_NODE) { result.append(subnode.getNodeValue()); } else if (subnode.getNodeType() == Node.ENTITY_REFERENCE_NODE) { // Recurse into the subtree for text // (and ignore comments) result.append(getText(subnode)); } } return result.toString(); } }