【问题标题】:Way to validate a Diameter URI in Java?在 Java 中验证 Diameter URI 的方法?
【发布时间】:2013-03-24 18:23:14
【问题描述】:

我想知道是否有任何不错的简单方法可以使用 Java 验证 Diameter URI(如下所述)?

Note, a Diameter URI must have one of the forms:

aaa://FQDN[:PORT][;transport=TRANS][;protocol=PROT]
aaas://FQDN[:PORT][;transport=TRANS][;protocol=PROT]

The FQDN (mandatory) has to be replaced with the fully qualified host name (or IP), the PORT (optional, default is 3868) with the port number, TRANS (optional) with the transport protocol (can be TCP or SCTP) and PROT (optional) with diameter.

Some examples of the acceptable forms are:

aaa://server.com
aaa://127.0.0.1
aaa://server.com:1234
aaas://server.com:1234;transport=tcp
aaas://[::1]
aaas://[::1]:1234
aaas://[::1]:1234;transport=tcp;protocol=diameter

Note, as shown above, if using an IPv6 address, the address must be placed in box brackets, whereas the port number (if specified), with its colon separator, should be outside of the brackets.

我认为使用正则表达式执行此操作会非常混乱且难以理解,而且我见过的其他不使用正则表达式的示例看起来也很尴尬(例如https://code.google.com/p/cipango/source/browse/trunk/cipango-diameter/src/main/java/org/cipango/diameter/util/AAAUri.java?r=763)。

所以想知道是否有更好的方法来做到这一点,例如类似于 URI 验证器库,它采用一些规则(例如上面的 Diameter URI 规则),然后将它们应用于某些输入以验证它?

我也查看了 Google Guava 库,看看是否有任何帮助,但我看不到任何东西。

非常感谢!

【问题讨论】:

  • 您是否尝试过简单地使用java.net.URI 构造函数,如果URI 无效,它将抛出URISyntaxException?
  • 是的,java.net.URI 的规则与我的用例略有不同。例如,接受新的 URI("127.0.0.1"),但这不是有效的直径 URI(开始时没有方案部分)
  • 为什么不用正则表达式解析出 FQDN:#aaas?://([^;]+)(;transport=\w+)?(;protocol=\w+)?#,然后在新的 URI 构造函数中使用子组 1 将其验证为 FQDN?
  • java.net.URI 仍然可以提供帮助:您只需要检查该方案是否为非空。这很方便,因为您已经想检查方案是“aaa”还是“aaas”。也就是说,您最终可能需要回退到正则表达式:Diameter URL 语法是一种奇怪的语法,不符合我所知道的任何 four URL 规范,所以标准 URL 类不太可能按照您需要的方式对其进行拆分。

标签: java regex uri guava diameter-protocol


【解决方案1】:

由于 URI 类是不够的,而且实际上会为有效的 Diameter URI 创建异常,所以这不是一项简单的任务。

我认为是 reg.ex。是去这里的方式,但由于复杂性,如果你把它放在一个助手类中可能会更好。我同意你链接到的代码看起来不太好——你可以做得更好! :)

看看下面的代码示例,我将一个正则表达式分解成各个部分,作为“记录”正在发生的事情的一种方式。

它在任何方面都不完整,它是根据您的示例创建的。特别是 IP6 类型的地址需要工作。此外,您可能希望在验证中提供更多信息;比如失败的原因。

但至少这是一个开始,而且我认为它比您链接到的代码要好得多。看起来可能有很多代码,但其中大部分实际上是打印语句和测试...... :) 此外,由于每个部分都被分解并保存为字段变量,因此您可以创建简单的 getter 来访问每个部分(如果这对您很重要)。

import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DiameterUri {

    private String diameterUri;
    private String protocol;
    private String host;
    private String port;
    private String[] params;

    public DiameterUri(String diameterUri) throws URISyntaxException {
        this.diameterUri = diameterUri;
        validate();
        System.out.println(diameterUri);
        System.out.println("  protocol=" + protocol);
        System.out.println("  host=" + host);
        System.out.println("  port=" + port);
        System.out.println("  params=" + Arrays.toString(params));
    }

    private void validate() throws URISyntaxException {
        String protocol = "(aaa|aaas)://";              // protocol- required
        String ip4 = "[A-Za-z0-9.]+";                   // ip4 address - part of "host"
        String ip6 = "\\[::1\\]";                       // ip6 address - part of "host"
        String host = "(" + ip4 + "|" + ip6 + ")";      // host - required
        String port = "(:\\d+)?";                       // port - optional (one occurrence)
        String params = "((;[a-zA-Z0-9]+=[a-zA-Z0-9]+)*)"; // params - optional (multiple occurrences)
        String regEx = protocol + host + port + params;
        Pattern pattern = Pattern.compile(regEx);
        Matcher matcher = pattern.matcher(diameterUri);
        if (matcher.matches()) {
            this.protocol = matcher.group(1);
            this.host = matcher.group(2);
            this.port = matcher.group(3) == null ? null : matcher.group(3).substring(1);
            String paramsFromUri = matcher.group(4);
            if (paramsFromUri != null && paramsFromUri.length() > 0) {
                this.params = paramsFromUri.substring(1).split(";");
            } else {
                this.params = new String[0];
            }
        } else {
            throw new URISyntaxException(diameterUri, "invalid");
        }
    }

    public static void main(String[] args) throws URISyntaxException {
        new DiameterUri("aaa://server.com");
        new DiameterUri("aaa://127.0.0.1");
        new DiameterUri("aaa://server.com:1234");
        new DiameterUri("aaas://server.com:1234;transport=tcp");
        new DiameterUri("aaas://[::1]");
        new DiameterUri("aaas://[::1]:1234");
        new DiameterUri("aaas://[::1]:1234;transport=tcp;protocol=diameter");
        try {
            new DiameterUri("127.0.0.1");
            throw new RuntimeException("Expected URISyntaxException");
        } catch (URISyntaxException ignore) {}
    }

}

【讨论】:

  • 非常感谢 Steinar,我认为这样的方法可能是最好的方法(你是对的,它比我链接的代码更干净!)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-16
  • 1970-01-01
  • 2020-10-23
  • 2022-06-16
  • 1970-01-01
  • 2011-03-23
相关资源
最近更新 更多