【问题标题】:Authentication of SOAP messagesSOAP 消息的身份验证
【发布时间】:2014-07-25 19:34:16
【问题描述】:

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

但是,我不认为回调是正确的地方,因为我不断收到密码,没有密码错误。我是 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>

回调:

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!");
            }

        } 
}

我的要求很简单: - 验证 SOAP 标头(有效) - 检索用户名和密码 - 调用我们的旧服务来创建我们的登录上下文 - 设置 spring 安全上下文(以 logincontext 作为详细信息),以便稍后在端点中使用

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

【问题讨论】:

    标签: spring-security spring-ws


    【解决方案1】:

    SpringSecurityPasswordValidationCallbackHandler 是给你的。来自 Spring WS 文档:

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

    <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>
    

    【讨论】:

    • 感谢您的回复,我仍然对这将如何工作感到困惑。 UserDetailsS​​ervice 类有一个 loadByUsername 方法,该方法返回一个 User 对象。我可以假设在调用此类之前已经完成了身份验证部分吗?
    • 所以我仍然需要实现一个回调处理程序来获取用户的密码。据我了解,我需要执行以下操作:1)实现一个回调 handleUSernameToken 方法,该方法从数据库中检索密码并将其设置在回调中,2)Spring通过将 SOAP 消息密码与我设置的密码匹配来验证用户名在回调中, 3) 实现 loadByUsername 方法来创建一个 User 对象。我将把我的自定义 LoginContext 对象放在这个方案中的什么位置,User 类似乎没有我可以使用的任何属性。
    • 不确定你为什么需要它。如果您使用WS-Security 关注请求中的所有内容...
    • 我想我现在明白了。我是从另一边接近这个问题的。基本上,我创建用户详细信息服务来加载用户对象,然后根据 SOAP 标头密码对其进行身份验证。不过,我还有另一个问题,我的数据库密码是加密的,那么在比较之前如何告诉 spring 加密 SOAP 消息中的密码?我无法解密密码,但确实有一种实用方法来加密字符串。
    • 查看 UsernameTokenValidatorUsernameToken 应该有助于了解密码的情况
    猜你喜欢
    • 1970-01-01
    • 2016-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多