Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何正确准备';HTTP重定向绑定';使用Java的SAML请求?_Java_Single Sign On_Saml 2.0_Shibboleth - Fatal编程技术网

如何正确准备';HTTP重定向绑定';使用Java的SAML请求?

如何正确准备';HTTP重定向绑定';使用Java的SAML请求?,java,single-sign-on,saml-2.0,shibboleth,Java,Single Sign On,Saml 2.0,Shibboleth,有一些测试资源,例如http://sometestresource.com我在http://sometestresource.com/Login我重定向到idP提供商:http://someidpprovoder.com/idp/authn/CommonLogin 嗅探器检测到重定向到https://someidpprovoder.com/idp/profile/SAML2/Redirect/SSO SAMLRequest=fZJda...D&RelayState=https%3A%2F

有一些测试资源,例如
http://sometestresource.com
我在
http://sometestresource.com/Login
我重定向到idP提供商:
http://someidpprovoder.com/idp/authn/CommonLogin

嗅探器检测到重定向到
https://someidpprovoder.com/idp/profile/SAML2/Redirect/SSO

SAMLRequest=fZJda...D&RelayState=https%3A%2F%2Fwww.sometestresource.com%2Fcms%2Fextentions%2Fsimplesaml%2Fwww%2Fmodule.php%2Fcore%2Fauthenticate.php%3Fas%3D100000za-sp
&SigAlg=http%3A%2F%2Fwww.w3.org%2F2000%2F09%2Fxmldsig%23rsa-sha1
&Signature=dAx0M...D
好的,我编写了一个简单的servlet应用程序,我希望获得相同的功能-

我的ServiceProvider servlet:

@WebServlet(urlPatterns={"/ServiceProvider"},
            initParams={ @WebInitParam(name="Issuer", value="some.issuer"),
                         @WebInitParam(name="IdpUrl", value="https://someidpprovoder.com/idp/profile/SAML2/Redirect/SSO"),
                         @WebInitParam(name="ConsumerUrl", value="http://localhost:8080/com.secure.isusia-1.0-SNAPSHOT/ServiceProvider")
            } )
public class ServiceProvider  extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private SamlConsumerManager consumer;

    public void init(ServletConfig config) throws ServletException {
        try {
            consumer = new SamlConsumerManager(config);
        } catch (ConfigurationException e) {
            throw new ServletException("Errow while configuring SAMLConsumerManager", e);
        }
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException,
            IOException {
        doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String responseMessage = request.getParameter("SAMLResponse");
        if (responseMessage != null) { 
            // response from the identity provider
            if (result == null) {
                // lets logout the user
            } else if (result.size() == 1) {
                 //
                 // No user attributes are returned, so just goto the default
                 //home page.
                 //
            } else if (result.size() > 1) {
                 // We have received attributes, so lets show them in the
                 // attribute home page.
                 //

            } else {
                // something wrong, re-login
            }
        } else { 
            /* time to create the authentication request or logout request */
        }
    }
}
我的SamlConsumerManager:

public class SamlConsumerManager {
    private String consumerUrl;
    private String authReqRandomId;
    private String relayState;
    private String issuerId;
    private String idpUrl;

    private char[] password = "...".toCharArray();
    private String alias = "...";

    private String sigAlg = "http://www.w3.org/2000/09/xmldsig#rsa-sha1";

    private Signature signature;
    private BasicX509Credential credential;
    private Element authDOM;

    public SamlConsumerManager(ServletConfig servletConfig) throws ConfigurationException {
        authReqRandomId = Integer.toHexString(new Double(Math.random()).intValue());        
        consumerUrl = servletConfig.getInitParameter("ConsumerUrl");
        idpUrl = servletConfig.getInitParameter("IdpUrl");
        issuerId = servletConfig.getInitParameter("Issuer");

        DefaultBootstrap.bootstrap();
    }

    public String buildRequestMessage(HttpServletRequest request) {

        RequestAbstractType requestMessage = null;

        if (request.getParameter("logout") == null) {
            // time to build the authentication request message
        } else { 
            // ok, user needs to be single logged out
        }

        String encodedRequestMessage = encodeRequestMessage(requestMessage);

        /* SAML2 Authentication Request is appended to IP's URL */
        return idpUrl + "?SAMLRequest=" + encodedRequestMessage + "&SigAlg=" + sigAlg;
    }

    private LogoutRequest buildLogoutRequest(String user) {
        LogoutRequest logoutReq = new LogoutRequestBuilder().buildObject();
        logoutReq.setID(Util.createID());

        DateTime issueInstant = new DateTime();
        logoutReq.setIssueInstant(issueInstant);
        logoutReq.setNotOnOrAfter(new DateTime(issueInstant.getMillis() + 5 * 60 * 1000));

        IssuerBuilder issuerBuilder = new IssuerBuilder();
        Issuer issuer = issuerBuilder.buildObject();
        issuer.setValue(issuerId);
        logoutReq.setIssuer(issuer);

        NameID nameId = new NameIDBuilder().buildObject();
        nameId.setFormat("urn:oasis:names:tc:SAML:2.0:nameid-format:entity");
        nameId.setValue(user);
        logoutReq.setNameID(nameId);

        SessionIndex sessionIndex = new SessionIndexBuilder().buildObject();
        sessionIndex.setSessionIndex(UIDGenerator.generateUID());
        logoutReq.getSessionIndexes().add(sessionIndex);

        logoutReq.setReason("Single Logout");

        return logoutReq;
    }

    private AuthnRequest buildAuthnRequestObject() {
        /* Building Issuer object */
        IssuerBuilder issuerBuilder = new IssuerBuilder();
        Issuer issuer = issuerBuilder.buildObject("urn:oasis:names:tc:SAML:2.0:assertion", "Issuer", "samlp");
        issuer.setValue(issuerId);

        /* NameIDPolicy */
        NameIDPolicyBuilder nameIdPolicyBuilder = new NameIDPolicyBuilder();
        NameIDPolicy nameIdPolicy = nameIdPolicyBuilder.buildObject();
        nameIdPolicy.setFormat("urn:oasis:names:tc:SAML:2.0:nameid-format:persistent");
        nameIdPolicy.setSPNameQualifier("Isser");
        nameIdPolicy.setAllowCreate(new Boolean(true));

        /* AuthnContextClass */
        AuthnContextClassRefBuilder authnContextClassRefBuilder = new AuthnContextClassRefBuilder();
        AuthnContextClassRef authnContextClassRef = authnContextClassRefBuilder.buildObject(
                        "urn:oasis:names:tc:SAML:2.0:assertion",
                        "AuthnContextClassRef",
                        "saml");

        authnContextClassRef.setAuthnContextClassRef("urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport");

        /* AuthnContex */
        RequestedAuthnContextBuilder requestedAuthnContextBuilder =
                new RequestedAuthnContextBuilder();
        RequestedAuthnContext requestedAuthnContext = requestedAuthnContextBuilder.buildObject();
        requestedAuthnContext.setComparison(AuthnContextComparisonTypeEnumeration.EXACT);
        requestedAuthnContext.getAuthnContextClassRefs().add(authnContextClassRef);

        DateTime issueInstant = new DateTime();

        /* Creation of AuthRequestObject */
        AuthnRequestBuilder authRequestBuilder = new AuthnRequestBuilder();
        AuthnRequest authRequest =
                authRequestBuilder.buildObject("urn:oasis:names:tc:SAML:2.0:protocol",
                        "AuthnRequest", "samlp");
        authRequest.setForceAuthn(new Boolean(false));
        authRequest.setIsPassive(new Boolean(false));
        authRequest.setIssueInstant(issueInstant);
        authRequest.setProtocolBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST");
        authRequest.setAssertionConsumerServiceURL(consumerUrl);
        authRequest.setIssuer(issuer);
        authRequest.setNameIDPolicy(nameIdPolicy);
        authRequest.setRequestedAuthnContext(requestedAuthnContext);
        authRequest.setID(authReqRandomId);
        authRequest.setVersion(SAMLVersion.VERSION_20);

        KeyStore  keyStore = KeyStore.getInstance(KeyStore.getDefaultType());

        FileInputStream fileInputStream = new FileInputStream(new File("....jks"));        

        keyStore.load(fileInputStream, password);
        fileInputStream.close();

        KeyStore.PrivateKeyEntry privateKeyEntry = null;
        privateKeyEntry = (KeyStore.PrivateKeyEntry) keyStore.getEntry(alias, new KeyStore.PasswordProtection(password));

        PrivateKey privateKey = privateKeyEntry.getPrivateKey();

        X509Certificate certificate = (X509Certificate) privateKeyEntry.getCertificate();

        credential = new BasicX509Credential();
        credential.setEntityCertificate(certificate);
        credential.setPrivateKey(privateKey);

        try {
            DefaultBootstrap.bootstrap();
        } catch (ConfigurationException e) {
            e.printStackTrace();
        }

        signature = (Signature) org.opensaml.xml.Configuration.getBuilderFactory().getBuilder(org.opensaml.xml.signature.Signature.DEFAULT_ELEMENT_NAME)
                .buildObject(org.opensaml.xml.signature.Signature.DEFAULT_ELEMENT_NAME);

        signature.setSigningCredential(credential);
        signature.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA1);
        signature.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);

        authRequest.setSignature(signature);

        return authRequest;
    }

    private String encodeRequestMessage(RequestAbstractType requestMessage)
            throws MarshallingException,
            IOException {

        Marshaller marshaller = Configuration.getMarshallerFactory().getMarshaller(requestMessage);
        Element authDOM = marshaller.marshall(requestMessage);

        Deflater deflater = new Deflater(Deflater.DEFLATED, true);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        DeflaterOutputStream deflaterOutputStream =
                new DeflaterOutputStream(byteArrayOutputStream,
                        deflater);

        StringWriter rspWrt = new StringWriter();
        XMLHelper.writeNode(authDOM, rspWrt);
        deflaterOutputStream.write(rspWrt.toString().getBytes());
        deflaterOutputStream.close();

        /* Encoding the compressed message */
        String encodedRequestMessage =
                Base64.encodeBytes(byteArrayOutputStream.toByteArray(),
                        Base64.DONT_BREAK_LINES);
        return URLEncoder.encode(encodedRequestMessage, "UTF-8").trim();
    }

}
然而,我得到的不是来自idP的登录页面,而是一个错误页面

我做错了什么?我想知道如何正确准备授权请求。例如,我不明白如何在URL中添加签名:

&Signature=dAx0M...D

更新

  • 我正在使用SP启动的Web SSO
  • 基于的远程idP(在客户方面,关于它我什么都不知道。只是它是基于Shibboleth编写的)

    • 您需要签名

      authRequest.setSignature(签名)下的
      buildAuthnRequestObject

      Signer
      being
      org.opensaml.xml.signature.Signer

      **更新**

      使用
      SAMLMessageContext
      HTTPRedirectDeflateEncoder

      public void doAuthenticationRedirect (HttpServletResponse response, final HttpSession currentSessiond) throws Exception {  
      
          /** Generate your authnrequest **/
          AuthnRequest authnRequest = generateAuthnRequest();  
      
          /** Create an adapter from tomcat response servlet **/
          HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(response, true); 
      
          /** 302 status code **/
          responseAdapter.setStatusCode(HttpServletResponse.SC_MOVED_TEMPORARILY);
      
          /** Build blank context **/
          SAMLMessageContext<?, AuthnRequest, ?> context =  SAMLUtility.makeSamlMessageContext();
      
          /** Set entity end point**/
          context.setPeerEntityEndpoint(endpointObject);  
      
          context.setOutboundSAMLMessage(authnRequest);  
      
         /** Sign this request **/
          context.setOutboundSAMLMessageSigningCredential(getSigningCredential());  
          context.setOutboundMessageTransport(responseAdapter);
           /** Run encoder **/
          try {  
              runEncoder(new HTTPRedirectDeflateEncoder(), context);
          } catch (Throwable t) {  
              Log.error("Error endcoding AuthnRequest: ",t);
          }  
      }  
      
      
       /** 
        * Encode our Context and send it
        * 
        * @param encoder
        * @param context
        * @throws IOException
        * @throws MessageEncodingException
        */
        private void runEncoder(MessageEncoder encoder, MessageContext context)      throws IOException, MessageEncodingException {
            encoder.encode(context);
        }
      

      我认为这个问题是你的代码> EnCODRealEdStimeStase<代码>方法,既然你正在使用OpenSSAML,为什么不让它为你重定向< <代码> SAMLMessageContext < /代码>和<代码> HTTPRedirectDeflateEncoder < /代码>我更新了我的答案,对不起在工作的中间,但是我试图尽可能多地解释。
      public void doAuthenticationRedirect (HttpServletResponse response, final HttpSession currentSessiond) throws Exception {  
      
          /** Generate your authnrequest **/
          AuthnRequest authnRequest = generateAuthnRequest();  
      
          /** Create an adapter from tomcat response servlet **/
          HttpServletResponseAdapter responseAdapter = new HttpServletResponseAdapter(response, true); 
      
          /** 302 status code **/
          responseAdapter.setStatusCode(HttpServletResponse.SC_MOVED_TEMPORARILY);
      
          /** Build blank context **/
          SAMLMessageContext<?, AuthnRequest, ?> context =  SAMLUtility.makeSamlMessageContext();
      
          /** Set entity end point**/
          context.setPeerEntityEndpoint(endpointObject);  
      
          context.setOutboundSAMLMessage(authnRequest);  
      
         /** Sign this request **/
          context.setOutboundSAMLMessageSigningCredential(getSigningCredential());  
          context.setOutboundMessageTransport(responseAdapter);
           /** Run encoder **/
          try {  
              runEncoder(new HTTPRedirectDeflateEncoder(), context);
          } catch (Throwable t) {  
              Log.error("Error endcoding AuthnRequest: ",t);
          }  
      }  
      
      
       /** 
        * Encode our Context and send it
        * 
        * @param encoder
        * @param context
        * @throws IOException
        * @throws MessageEncodingException
        */
        private void runEncoder(MessageEncoder encoder, MessageContext context)      throws IOException, MessageEncodingException {
            encoder.encode(context);
        }
      
       public static <TI extends SAMLObject, TO extends SAMLObject, TN extends SAMLObject>
          SAMLMessageContext<TI, TO, TN> makeSamlMessageContext() {
            return new BasicSAMLMessageContext<TI, TO, TN>();
       }