SAML基于sp的身份验证具有以下简短的工作流程.
>用户想要访问sp.
> sp发送SAMLRequest令牌到idp.
> idp消耗它并生成SAMLResponse令牌.
> idp将此SAMLResponse令牌发送到由sp给出的AC-URL.
我的问题是如何使用这个SAMLResponse令牌.
什么是逻辑?
如果我可以得到一些JAVA代码的帮助,这将是有益的.
解决方法
下一个食谱正在为我工作:
>获取SAMLResponse令牌并对其进行解码并充气:
// Base64 decode Base64 base64Decoder = new Base64(); byte[] xmlBytes = encodedXmlString.getBytes("UTF-8"); byte[] base64DecodedByteArray = base64Decoder.decode(xmlBytes); // Inflate (uncompress) the AuthnRequest data // First attempt to unzip the byte array according to DEFLATE (rfc 1951) Inflater inflater = new Inflater(true); inflater.setInput(base64DecodedByteArray); // since we are decompressing,it's impossible to know how much space we // might need; hopefully this number is suitably big byte[] xmlMessageBytes = new byte[5000]; int resultLength = inflater.inflate(xmlMessageBytes); if (!inflater.finished()) { throw new RuntimeException("didn't allocate enough space to hold " + "decompressed data"); } inflater.end(); String decodedResponse = new String(xmlMessageBytes,resultLength,"UTF-8"); return decodedResponse;
>解析生成的XML.在这里,您可以获得所需的信息,例如,使用它创建一个POJO(这是用于解析logoutRequest的示例代码,但是类似于响应):
// Parse the XML. SAX approach,we just need the ID attribute SAXParserFactory saxParserFactory = SAXParserFactory.newInstance(); // If we want to validate the doc we need to load the DTD // saxParserFactory.setValidating(true); // Get a SAXParser instance SAXParser saxParser = saxParserFactory.newSAXParser(); // Parse it XMLhandler xmLhandler = new XMLhandler(); saxParser.parse(new ByteArrayInputStream(xmllogoutRequest.getBytes()),xmLhandler); // Return the SamlVO return xmLhandler.getSamlVO();
对于我的用例我很有趣的只有几个元素,所以我使用SAX:
public class XMLhandler extends DefaultHandler { private SamlVO samlVO; public XMLhandler() { samlVO = new SamlVO(); } @Override public void startElement(String uri,String localName,String qName,Attributes attributes) throws SAXException { // Managing a logoutRequest means that we are going to build a logoutResponse if (qName.equals("samlp:logoutRequest")) { // The ID value of a request will be the logoutResponse's InReponseTo attribute samlVO.setInResponseTo(attributes.getValue("ID")); // From the destination we can get the Issuer element String destination = attributes.getValue("Destination"); if (destination != null) { URL destinationUrl = null; try { destinationUrl = new URL(destination); } catch (MalformedURLException e) { // TODO: We could set the server hostname (take it from a property),but this URL SHOULD be well formed! e.printStackTrace(); } samlVO.setIssuer(destinationUrl.getHost()); } } } public SamlVO getSamlVO() { return samlVO; } }
希望有帮助,
路易斯
PS:你也可以使用像OpenSAML这样的图书馆
DefaultBootstrap.bootstrap(); HTTPRedirectDeflateDecoder decode = new HTTPRedirectDeflateDecoder(new BasicParserPool()); BasicSAMLMessageContext<logoutRequest,?,?> messageContext = new BasicSAMLMessageContext<logoutRequest,SAMLObject,SAMLObject>(); messageContext.setInboundMessageTransport(new HttpServletRequestAdapter(request)); decode.decode(messageContext); XMLObjectBuilderFactory builderFactory = org.opensaml.Configuration.getBuilderFactory(); logoutRequestBuilder logoutRequestBuilder = (logoutRequestBuilder) builderFactory.getBuilder(logoutRequest.DEFAULT_ELEMENT_NAME); logoutRequest logoutRequest = logoutRequestBuilder.buildObject(); logoutRequest = (logoutRequest) messageContext.getInboundMessage();
但是准备在你的CLASSPATH中包含几个库!