首页 > 解决方案 > Opensaml- HTTPPostEncoder encoder.encode() - 发送响应和重定向

问题描述

我已经编写了一种将 SAML 响应发送到 ACS url 并将用户重定向到 SP 的方法。方法是:

public static void sendPostMessage(HttpServletResponse response, SAMLObject message, String url, String relayState) throws OpenSAMLException {
    logger.info("Starting to post SAML Response...");

    MessageContext<SAMLObject> context = new MessageContext();
    context.setMessage(message);
    Endpoint endpoint = OpenSAMLUtils.createSAMLObject(AssertionConsumerService.class);
    endpoint.setLocation(url);
    SAMLPeerEntityContext peerEntityContext = context.getSubcontext(SAMLPeerEntityContext.class, true);
    SAMLEndpointContext endpointContext = peerEntityContext.getSubcontext(SAMLEndpointContext.class, true);
    endpointContext.setEndpoint(endpoint);

    SAMLBindingContext bindingContext = context.getSubcontext(SAMLBindingContext.class, true);
    bindingContext.setRelayState(relayState);

    HTTPPostEncoder encoder = new HTTPPostEncoder();
    encoder.setVelocityEngine(getVelocityEngine());
    encoder.setMessageContext(context);
    encoder.setHttpServletResponse(response);
    try {
        encoder.initialize();
    } catch (ComponentInitializationException e) {
        throw new RuntimeException(e);
    }
    try {
        encoder.encode();         //POST the message and redirect
    } catch (MessageEncodingException e) {
        throw new RuntimeException(e);
    }
    logger.info("SAML response posted successfully...");
}

我在两个实例中调用此方法

1)

@POST
    @Consumes("application/x-www-form-urlencoded")
    public javax.ws.rs.core.Response doSSO(@FormParam("SAMLRequest") String encodedSAMLRequest,
                                           @FormParam("RelayState") String relayState,
                                           @Context HttpServletResponse httpServletResponse,
                                           @CookieParam(USERNAME_COOKIE) String username) throws OpenSAMLException, SAMLTokenGenerationException, URISyntaxException, UnsupportedEncodingException, ServletException {
        if (username != null) {
            logger.info("User {} is already logged in.", username);
            //build the SAML response
            Object requestXmlObj = SAMLMessageHandler.getAuthnRequestSamlObject(encodedSAMLRequest);
            AuthnRequest authnRequest = (AuthnRequest) requestXmlObj;
            Response response = SAMLMessageHandler.buildSamlResponse(authnRequest, username);
            SAMLMessageHandler.sendPostMessage
                    (httpServletResponse, response, authnRequest.getAssertionConsumerServiceURL(), relayState); //**sendPostMessage**
            return javax.ws.rs.core.Response.ok().build();
        } else {
            NewCookie samlReqCookie = new NewCookie(SAMLREQ_COOKIE, encodedSAMLRequest, "/", null, null, MAX_AGE, false, true);
            NewCookie relayStateCookie = new NewCookie(RELAYSTATE_COOKIE, relayState, "/", null, null, MAX_AGE, false, true);
            return javax.ws.rs.core.Response.seeOther(URI.create("/portal/login"))
                    .cookie(samlReqCookie, relayStateCookie)
                    .build();
        }
    }
@Path("/login")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response login(String login,
                          @CookieParam(SAMLREQ_COOKIE) Cookie encodedAuthnReq,
                          @CookieParam(RELAYSTATE_COOKIE) Cookie relayState,
                          @Context HttpServletResponse httpServletResponse)
            throws IOException, OpenSAMLException, SAMLTokenGenerationException, URISyntaxException {

        Map<String, String> loginMap = objectMapper.readValue(login, new TypeReference<HashMap<String, String>>() {
        });
        if (encodedAuthnReq != null) {
            //build the SAML response
            Object requestXmlObj = SAMLMessageHandler.getAuthnRequestSamlObject(encodedAuthnReq.getValue());
            AuthnRequest authnRequest = (AuthnRequest) requestXmlObj;
            org.opensaml.saml.saml2.core.Response response =
                    SAMLMessageHandler.buildSamlResponse(authnRequest, loginMap.get("username"));
            SAMLMessageHandler.sendPostMessage
                    (httpServletResponse, response, authnRequest.getAssertionConsumerServiceURL(), relayState.getValue()); //**sendPostMessage**
            return javax.ws.rs.core.Response.ok().build();

        } else {
            return Response.seeOther(URI.create("/portal/login-success"))
                    .cookie(new NewCookie(USERNAME_COOKIE, loginMap.get("username"), "/", null, null, MAX_AGE, false, true))
                    .build();
        }
    }

虽然它在第一种情况下按预期工作(能够发布消息并将用户重定向到 SP 页面),但在第二种情况下,不会发生 POST 和重定向。我尝试调试代码,但找不到任何东西。

注意-我在最后一次调用时使用 OpenSAML3 库和 encoder.encode() (opensaml-saml-impl-3.4.6.jar):

            Writer out = new OutputStreamWriter(response.getOutputStream(), "UTF-8");
            this.velocityEngine.mergeTemplate(this.velocityTemplateId, "UTF-8", context, out);
            out.flush();

标签: javajax-rssaml-2.0opensamlidp

解决方案


推荐阅读