Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/powershell/11.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
Spring security SOAP消息的身份验证_Spring Security_Spring Ws - Fatal编程技术网

Spring security SOAP消息的身份验证

Spring security SOAP消息的身份验证,spring-security,spring-ws,Spring Security,Spring Ws,我已经找了一个好的例子,但找不到一个。我想从SOAP头中获取用户名和密码,并在使用现有服务方法进行身份验证后设置spring安全上下文。我已经实现了Wss4jSecurityInterceptor,它验证了header元素。在回调或其他机制中,我需要做的是创建一个授权上下文,以便稍后在端点中访问它 然而,我不认为回调是正确的地方做这件事,因为我一直得到密码提供没有密码错误。我不熟悉spring安全和集成 配置: <bean id="SOAPSecurityInterceptor"

我已经找了一个好的例子,但找不到一个。我想从SOAP头中获取用户名和密码,并在使用现有服务方法进行身份验证后设置spring安全上下文。我已经实现了Wss4jSecurityInterceptor,它验证了header元素。在回调或其他机制中,我需要做的是创建一个授权上下文,以便稍后在端点中访问它

然而,我不认为回调是正确的地方做这件事,因为我一直得到密码提供没有密码错误。我不熟悉spring安全和集成

配置:

     <bean id="SOAPSecurityInterceptor" class="com.ps.snt.ws.interceptor.SOAPSecurityInterceptor"> 
        <property name="validationActions" value="UsernameToken"/> 
        <property name="validationCallbackHandler" ref="callbackHandler"/>
    </bean> 
    <bean id="callbackHandler" class="com.ps.snt.ws.interceptor.SOAPSecurityValidationCallbackHandler">
   </bean>
我的要求很简单: -验证SOAP头(工作) -检索用户名和密码 -调用遗留服务来创建登录上下文 -设置spring安全上下文(详细信息为logincontext),以便稍后在端点中使用


我可以使用什么机制来验证soap头并从该头设置安全上下文

SpringSecurityPasswordValidationCallbackHandler是为您准备的。从Spring WS文档:

SpringSecurityPasswordValidationCallbackHandler使用SpringSecurityUserDetailService来验证纯文本和摘要密码。它使用此服务检索令牌中指定的用户的密码(摘要)。然后将此详细信息对象中包含的密码(摘要)与消息中的摘要进行比较。如果它们相等,则表示用户已成功进行身份验证,并且UsernamePasswordAuthenticationToken存储在SecurityContextHolder中。您可以使用userDetailsService设置服务。此外,还可以设置userCache属性,以缓存加载的用户详细信息


...

感谢您的回复,我仍然不知道这将如何工作。UserDetailsService类有一个loadByUsername方法,该方法返回一个用户对象。我可以假设在调用这个类之前已经完成了身份验证部分吗?所以我仍然需要实现一个回调处理程序来获取用户的密码。据我所知,我需要执行以下操作:1)实现一个回调handleUSernameToken方法,该方法从数据库检索密码并在回调中设置密码,2)Spring通过将SOAP消息密码与我在回调中设置的密码匹配来验证用户名,3)实现loadByUsername方法以创建用户对象。在这个方案中,我将把我的自定义LoginContext对象放在哪里,用户类似乎没有我可以使用的任何属性。不确定为什么需要它。如果您遵循
WS-Security
的要求,那么请求中应该包含所有内容……我想我现在理解了。我是从另一方面来处理这个问题的。基本上,我创建user details服务来加载用户对象,然后根据SOAP头密码对其进行身份验证。不过,我还有一个问题,数据库中的密码是加密的,那么在比较之前,如何告诉spring在SOAP消息中加密密码呢?我无法解密密码,但确实有一个实用方法来加密字符串。请参阅
UsernameTokenValidator
UsernameToken
有助于了解密码的情况
public class SOAPSecurityValidationCallbackHandler extends  SimplePasswordValidationCallbackHandler {

     @Override
        protected void handleUsernameToken(WSPasswordCallback callback) throws IOException, UnsupportedCallbackException {
            System.out.println("In security callback " + callback.getPassword());

            boolean valid = true;

            String token = callback.getIdentifier();
            String password = callback.getPassword();
            Integer zoneID = null;

            String username = null;


            StringBuffer errorMessages = new StringBuffer();

            if(StringUtils.isEmpty(token)) {
                errorMessages.append("Username token cannot be empty");
                valid = false;
            } else {
                Pattern pattern = Pattern.compile("^[\\w]+\\d\\d\\d\\d\\d");
                Matcher matcher = pattern.matcher(token);
                if(!matcher.matches()) {
                    valid = false;
                    errorMessages.append("Username token must be in the format 'user@zone'.");
                }
                else {
                    String[] parts = token.split("@");
                    username = parts[0];
                    zoneID = Integer.parseInt(parts[1]);
                }

            }

            if(StringUtils.isEmpty(password)) {
                errorMessages.append("Password cannot be empty.");
                valid = false;
            }


            if(valid && username != null && zoneID != null) {
                LoginService loginService = new LoginService();
                LoginContextDO loginContextDO = loginService.getAuthenticatedLoginContext(username, password, zoneID);

                AbstractAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, password);
                authentication.setDetails(loginContextDO);
                authentication.setAuthenticated(true);

                SecurityContextHolder.getContext().setAuthentication(authentication);


            } else {
                System.out.println("Authetnication failed!");
            }

        } 
}
<beans>
    <bean class="org.springframework.ws.soap.security.wss4j.callback.SpringDigestPasswordValidationCallbackHandler">
        <property name="userDetailsService" ref="userDetailsService"/>
    </bean>

    <bean id="userDetailsService" class="com.mycompany.app.dao.UserDetailService" />
    ...
</beans>