我有以下情况: 记录用户正在访问Web应用程序的安全部分,该部分显示从安全Web服务获取的数据。
问题: 如何将用户凭据传播到Web服务?我已经关注了Keycloak web site上的教程,因此我可以在EJB中访问用户凭据进行Web服务调用,但它们不会传播到Web服务中。我缺少什么才能获得凭证?
应用程序服务器是Wildfly 10.1,身份提供者Keycloak 2.2.1
Wildfly standalone.xml的一部分:
<extensions>
<extension module="org.keycloak.keycloak-saml-adapter-subsystem"/>
...
</extensions>
<profile>
<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1">
<secure-deployment name="secappOne.war">
<SP entityID="secappOne" sslPolicy="EXTERNAL" logoutPage="logout.jsp">
<Keys>
<Key signing="true">
<PrivateKeyPem>...</PrivateKeyPem>
<CertificatePem>...</CertificatePem>
</Key>
</Keys>
<IDP entityID="idp" signatureAlgorithm="RSA_SHA256" signatureCanonicalizationMethod="http://www.w3.org/2001/10/xml-exc-c14n#">
<SingleSignOnService signRequest="true" validateResponseSignature="true" validateAssertionSignature="false" requestBinding="POST" bindingUrl="http://localworker.net:8180/auth/realms/applications/protocol/saml"/>
<SingleLogoutService validateRequestSignature="true" validateResponseSignature="true" signRequest="true" signResponse="true" requestBinding="POST" responseBinding="POST" postBindingUrl="http://localworker.net:8180/auth/realms/applications/protocol/saml" redirectBindingUrl="http://localworker.net:8180/auth/realms/applications/protocol/saml"/>
<Keys>
<Key signing="true">
<CertificatePem>...</CertificatePem>
</Key>
</Keys>
</IDP>
</SP>
</secure-deployment>
</subsystem>
<subsystem xmlns="urn:jboss:domain:security:1.2">
<security-domains>
<security-domain name="keycloak">
<authentication>
<login-module code="org.keycloak.adapters.jboss.KeycloakLoginModule" flag="required"/>
</authentication>
</security-domain>
</security-domains>
...
</subsystem>
...
</profile>
Web应用程序包含一些Web页面和EJB,用于调用Web服务。这被部署为WAR。用户凭证传播到EJB,通过@RolesAllowed(“allMighty”)进行Web服务调用和授权工作正常。
的web.xml:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>secappOne</display-name>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
<security-constraint>
<display-name>SecurityConstraint</display-name>
<web-resource-collection>
<web-resource-name>seccappOneWR</web-resource-name>
<url-pattern>/secured/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>allMighty</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>KEYCLOAK-SAML</auth-method>
</login-config>
<security-role>
<role-name>allMighty</role-name>
</security-role>
</web-app>
的JBoss-web.xml中:
<jboss-web>
<security-domain>keycloak</security-domain>
</jboss-web>
EJB:
@Stateless
@RolesAllowed("allMighty")
public class SimpleDao {
@WebServiceRef(wsdlLocation = "http://localhost:8080/secwsOne-1.0-SNAPSHOT/SimpleService/SimpleWS?wsdl")
private SimpleService simpleService;
public Date getCurrentDate() {
GetDateResponse response = simpleService.getSimpleSOAP().getDate(new GetDateRequest());
return response.getDate().toGregorianCalendar().getTime();
}
}
的JBoss-ejb3.xml:
<?xml version="1.0" encoding="UTF-8"?>
<jboss:ejb-jar
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:s="urn:security:1.1"
version="3.1" impl-version="2.0">
<assembly-descriptor>
<s:security>
<!-- EJB name or wildcard * is supported -->
<ejb-name>*</ejb-name>
<!-- Name of the security domain which is configured in the EJB3 subsystem -->
<s:security-domain>keycloak</s:security-domain>
</s:security>
</assembly-descriptor>
</jboss:ejb-jar>
Web服务是部署为JAR的不同模块中的另一个EJB。
EJB:
@Stateless
@WebService(
endpointInterface = "com.example.ws.simpleservice.SimplePort",
targetNamespace = "http://example.com/ws/SimpleService",
portName = "SimpleSOAP",
serviceName = "SimpleService",
wsdlLocation = "wsdl/simple.wsdl")
public class SimpleWS implements SimplePort {
@Override
@RolesAllowed("allMighty")
public GetDateResponse getDate(GetDateRequest request) {
GetDateResponse response = new GetDateResponse();
response.setDate(new Date());
return response;
}
}
的JBoss-ejb3.xml:
<?xml version="1.0" encoding="UTF-8"?>
<jboss:ejb-jar
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:s="urn:security:1.1"
version="3.1" impl-version="2.0">
<assembly-descriptor>
<s:security>
<!-- EJB name or wildcard * is supported -->
<ejb-name>*</ejb-name>
<!-- Name of the security domain which is configured in the EJB3 subsystem -->
<s:security-domain>keycloak</s:security-domain>
</s:security>
</assembly-descriptor>
</jboss:ejb-jar>
WS调用失败:
09:42:33,770 ERROR [org.jboss.as.ejb3.invocation] (default task-10) WFLYEJB0034: EJB Invocation failed on component SimpleWS for method public com.example.ws.simpleservice.dto.GetDateResponse com.example.ws.SimpleWS.getDate(com.example.ws.simpleservice.dto.GetDateRequest): javax.ejb.EJBAccessException: WFLYEJB0364: Invocation on method: public com.example.ws.simpleservice.dto.GetDateResponse com.example.ws.SimpleWS.getDate(com.example.ws.simpleservice.dto.GetDateRequest) of bean: SimpleWS is not allowed
at org.jboss.as.ejb3.security.AuthorizationInterceptor.processInvocation(AuthorizationInterceptor.java:134)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:100)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:66)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.as.ejb3.component.interceptors.AdditionalSetupInterceptor.processInvocation(AdditionalSetupInterceptor.java:54)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.ContextClassLoaderInterceptor.processInvocation(ContextClassLoaderInterceptor.java:64)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:356)
at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:636)
at org.jboss.invocation.AccessCheckingInterceptor.processInvocation(AccessCheckingInterceptor.java:61)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:356)
at org.jboss.invocation.PrivilegedWithCombinerInterceptor.processInvocation(PrivilegedWithCombinerInterceptor.java:80)
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:340)
at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
at org.jboss.as.ee.component.ViewService$View.invoke(ViewService.java:195)
at org.jboss.as.webservices.invocation.AbstractInvocationHandler.invoke(AbstractInvocationHandler.java:137)
at org.jboss.wsf.stack.cxf.JBossWSInvoker.performInvocation(JBossWSInvoker.java:169)
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96)
at org.apache.cxf.jaxws.AbstractJAXWSMethodInvoker.invoke(AbstractJAXWSMethodInvoker.java:232)
at org.apache.cxf.jaxws.JAXWSMethodInvoker.invoke(JAXWSMethodInvoker.java:85)
at org.jboss.wsf.stack.cxf.JBossWSInvoker.invoke(JBossWSInvoker.java:145)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor$2.run(ServiceInvokerInterceptor.java:126)
at org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:131)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:251)
at org.jboss.wsf.stack.cxf.RequestHandlerImpl.handleHttpRequest(RequestHandlerImpl.java:108)
at org.jboss.wsf.stack.cxf.transport.ServletHelper.callRequestHandler(ServletHelper.java:134)
at org.jboss.wsf.stack.cxf.CXFServletExt.invoke(CXFServletExt.java:88)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:293)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:212)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
at org.jboss.wsf.stack.cxf.CXFServletExt.service(CXFServletExt.java:136)
at org.jboss.wsf.spi.deployment.WSFServlet.service(WSFServlet.java:140)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:285)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:264)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:175)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:792)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
我还需要做些什么才能通过SOAP调用传递凭据?还有SAML配置吗?