我正在使用这个非常棒的插件http://grails.org/plugin/cxf-client来使用具有安全性的契约优先Web服务。
所以我的配置中已经有类似的东西了:
cxf {
client {
cybersourceClient {
clientInterface = com.webhost.soapProcessor
serviceEndpointAddress = "https://webhost/soapProcessor"
wsdl = "https://webhost/consumeMe.wsdl"
secured = true
username = "myUname"
password = "myPwd"
}
}
这非常有效,但我现在要做的是为我的用户提供输入用户名和密码的权限,以便他们输入用户名和密码来使用该服务。有谁知道怎么做?
我怀疑它在演示项目中使用了Custom In Interceptor:
package com.cxf.demo.security
import com.grails.cxf.client.CxfClientInterceptor
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor
import org.apache.ws.security.WSPasswordCallback
import org.apache.ws.security.handler.WSHandlerConstants
import javax.security.auth.callback.Callback
import javax.security.auth.callback.CallbackHandler
import javax.security.auth.callback.UnsupportedCallbackException
class CustomSecurityInterceptor implements CxfClientInterceptor {
String pass
String user
WSS4JOutInterceptor create() {
Map<String, Object> outProps = [:]
outProps.put(WSHandlerConstants.ACTION, org.apache.ws.security.handler.WSHandlerConstants.USERNAME_TOKEN)
outProps.put(WSHandlerConstants.USER, user)
outProps.put(WSHandlerConstants.PASSWORD_TYPE, org.apache.ws.security.WSConstants.PW_TEXT)
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, new CallbackHandler() {
void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]
pc.password = pass
pc.identifier = user
}
})
new WSS4JOutInterceptor(outProps)
}
}
但由于我没有实例化这个拦截器,或者理解它是如何实例化的,我不知道如何获得拦截器中使用的用户凭据。
有谁知道怎么做/有任何示例代码?
谢谢!
答案 0 :(得分:0)
假设您正在使用Spring Security插件,并且您要使用的WS凭据是User
域对象的属性,那么这样的东西应该可以工作(未经测试):
<强>的src /常规/ COM / CXF /演示/安全/ CustomSecurityInterceptor.groovy 强>
package com.cxf.demo.security
import com.grails.cxf.client.CxfClientInterceptor
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor
import org.apache.ws.security.WSPasswordCallback
import org.apache.ws.security.handler.WSHandlerConstants
import javax.security.auth.callback.Callback
import javax.security.auth.callback.CallbackHandler
import javax.security.auth.callback.UnsupportedCallbackException
class CustomSecurityInterceptor implements CxfClientInterceptor {
def springSecurityService
def grailsApplication
WSS4JOutInterceptor create() {
Map<String, Object> outProps = [:]
outProps.put(WSHandlerConstants.ACTION, org.apache.ws.security.handler.WSHandlerConstants.USERNAME_TOKEN)
// take default username from config
outProps.put(WSHandlerConstants.USER, grailsApplication.config.cxf.client.cybersourceClient.username)
outProps.put(WSHandlerConstants.PASSWORD_TYPE, org.apache.ws.security.WSConstants.PW_TEXT)
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, new CallbackHandler() {
void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]
// take password from current user, fall back to config if no
// user currently logged in/not in a request thread, etc.
pc.password = (springSecurityService.currentUser?.wsPassword
?: grailsApplication.config.cxf.client.cybersourceClient.password)
}
})
new CustomWSS4JOutInterceptor(springSecurityService, outProps)
}
}
class CustomWSS4JOutInterceptor extends WSS4JOutInterceptor {
def springSecurityService
CustomWSS4JOutInterceptor(springSecurityService, outProps) {
super(outProps)
this.springSecurityService = springSecurityService
}
// overridden to fetch username dynamically from logged in user
// but fall back on config if no user/not on a request hander thread
public Object getOption(String key) {
if(key == WSHandlerConstants.USER && springSecurityService.currentUser?.wsUser) {
return springSecurityService.currentUser?.wsUser
} else return super.getOption(key)
}
}
<强>的grails-app / CONF /弹簧/ resources.groovy 强>
import com.cxf.demo.security.CustomSecurityInterceptor
beans = {
customSecurityInterceptor(CustomSecurityInterceptor) {
springSecurityService = ref('springSecurityService')
grailsApplication = ref('grailsApplication')
}
}
并在配置中,将secured = true
替换为securityInterceptor = 'customSecurityInterceptor'
如果您不使用Spring Security,则相同的模式将起作用。关键位是回调处理程序
pc.password = (springSecurityService.currentUser?.wsPassword
?: grailsApplication.config.cxf.client.cybersourceClient.password)
和getOption
if(key == WSHandlerConstants.USER && springSecurityService.currentUser?.wsUser) {
return springSecurityService.currentUser?.wsUser
例如,如果用户名和密码存储在HTTP会话中,那么您可以使用Spring RequestContextHolder而不是springSecurityService
,其静态getRequestAttributes()
方法返回正在处理的GrailsWebRequest当前线程,如果当前线程没有处理请求,则为null(例如,如果它是后台作业)。
RequestContextHolder.requestAttributes?.session?.wsUser
或者,如果他们是请求属性(即您在控制器中说过request.wsUser = 'realUsername'
),则可以使用RequestContextHolder.requestAttributes?.currentRequest?.wsUser
。
答案 1 :(得分:0)
以下是其他任何人的通用答案:
<强> 1。 Config.groovy中强>
cxf {
client {
nameOfClient {
clientInterface = com.webhost.soapProcessor
serviceEndpointAddress = "https://webhost/soapProcessor"
wsdl = "https://webhost/soapProcessorconsumeMe.wsdl"
secured = true
securityInterceptor = "nameOfSecurityInterceptorBean"
}
}
}
<强> 2。 Resources.groovy 强>
import com.company.package.MySecurityInterceptor
beans = {
nameOfSecurityInterceptorBean(MySecurityInterceptor) {
}
}
第3。在com.company.package
下创建一个MySecurityInterceptorpackage com.company.package;
import com.grails.cxf.client.CxfClientInterceptor
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor
import org.apache.ws.security.WSPasswordCallback
import org.apache.ws.security.handler.WSHandlerConstants
import javax.security.auth.callback.Callback
import javax.security.auth.callback.CallbackHandler
import javax.security.auth.callback.UnsupportedCallbackException
import org.springframework.web.context.request.RequestContextHolder
class MySecurityInterceptor implements CxfClientInterceptor {
WSS4JOutInterceptor create() {
Map<String, Object> outProps = [:]
outProps.put(WSHandlerConstants.ACTION, org.apache.ws.security.handler.WSHandlerConstants.USERNAME_TOKEN)
outProps.put(WSHandlerConstants.USER, user)
outProps.put(WSHandlerConstants.PASSWORD_TYPE, org.apache.ws.security.WSConstants.PW_TEXT)
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, new CallbackHandler() {
void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0]
def requestObj = RequestContextHolder.requestAttributes?.currentRequest
pc.password = requestObj.soapPassword
pc.identifier = requestObj.soapIdentifier
}
})
new WSS4JOutInterceptor(outProps)
}
}
<强> 4。现在我们需要将用户名和密码放入请求(线程安全)中,以便拦截器取出:
import com.company.package.MySecurityInterceptor
class MySoapSendingController {
SoapProcessor nameOfClient
def index() {
request['soapIdentifier'] = "usernameToUse"
request['soapPassword'] = "passwordToUse"
...
ReplyMessage replyMsg = nameOfClient.makeSOAPRequest(request)
}
}