使用SAMLResponse令牌

时间:2011-07-13 15:07:02

标签: java authentication saml opensaml saml-2.0

基于SAML sp的身份验证具有以下简短的工作流程。

  • 用户希望在sp。
  • 访问应用程序
  • sp将SAMLRequest令牌发送给idp。
  • idp使用它并生成SAMLResponse令牌。
  • idp将此SAMLResponse令牌发送到sp。
  • 给出的AC-URL

我的问题是sp如何使用此SAMLResponse令牌。 逻辑是什么? 如果我能获得一些JAVA代码帮助它将是有益的。

3 个答案:

答案 0 :(得分:14)

下一个食谱对我有用:

  1. 获取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, 0, resultLength,
            "UTF-8");
    
    return decodedResponse;
    
  2. 解析生成的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();
    
  3. 对于我的用例,我只对几个元素感兴趣,所以我使用 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中包含几个库!!!

答案 1 :(得分:1)

要求代码有点多,但基本处理是SP验证SAMLResponse,包括良好格式,所需值的存在,正确的协议以及任何其他SP特定的验证(时间限制,数据通信)等),将在令牌中识别的用户映射到SP上的用户(可能涉及创建用户),并将用户转移到所请求的资源。

答案 2 :(得分:1)

以下是我在Java中的使用方法。我使用XMLBeans来解析SAMLResponse,然后对其进行解密(如果它已加密),然后验证签名:

WebBrowserSSOAuthConsumerService