lil*_*ien 5 grails groovy cxf credentials wss4j
我正在使用这个非常棒的插件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"
}
}
Run Code Online (Sandbox Code Playgroud)
这非常有效,但我现在要做的是为我的用户提供输入用户名和密码的权限,以便他们输入用户名和密码来使用该服务.有谁知道如何做到这一点?
我怀疑它在演示项目中使用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)
}
}
Run Code Online (Sandbox Code Playgroud)
但是因为我没有实例化这个拦截器,或者理解它是如何实例化的,所以我不知道如何获得拦截器中使用的用户凭据.
有谁知道如何做/有任何示例代码?
谢谢!
假设您正在使用 Spring Security 插件,并且您想要使用的 WS 凭证是User域对象的属性,那么类似这样的事情应该可以工作(未经测试):
src/groovy/com/cxf/demo/security/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)
}
}
Run Code Online (Sandbox Code Playgroud)
grails-app/conf/spring/resources.groovy
import com.cxf.demo.security.CustomSecurityInterceptor
beans = {
customSecurityInterceptor(CustomSecurityInterceptor) {
springSecurityService = ref('springSecurityService')
grailsApplication = ref('grailsApplication')
}
}
Run Code Online (Sandbox Code Playgroud)
并在配置中替换secured = true为securityInterceptor = 'customSecurityInterceptor'
如果您不使用 Spring Security,则相同的模式也可以工作。关键的部分是回调处理程序
pc.password = (springSecurityService.currentUser?.wsPassword
?: grailsApplication.config.cxf.client.cybersourceClient.password)
Run Code Online (Sandbox Code Playgroud)
和用户名逻辑getOption
if(key == WSHandlerConstants.USER && springSecurityService.currentUser?.wsUser) {
return springSecurityService.currentUser?.wsUser
Run Code Online (Sandbox Code Playgroud)
例如,如果用户名和密码存储在 HTTP 会话中,那么springSecurityService您可以使用 Spring RequestContextHolder来代替,它的静态getRequestAttributes()方法返回当前线程正在处理的 GrailsWebRequest ,如果当前线程未处理请求,则返回 null (例如,如果它是后台作业)。
RequestContextHolder.requestAttributes?.session?.wsUser
Run Code Online (Sandbox Code Playgroud)
request.wsUser = 'realUsername'或者,如果它们是请求属性(即您在控制器中所说的),您可以使用RequestContextHolder.requestAttributes?.currentRequest?.wsUser.
| 归档时间: |
|
| 查看次数: |
2518 次 |
| 最近记录: |