27、Java平台安全机制与JSSE详解

Java平台安全机制与JSSE详解

1. Java GSS - API安全上下文

在Java中,若两个应用程序要使用GSS - API安全地交换消息,它们必须先建立一个联合安全上下文。 org.ietf.jgss.GSSContext 接口封装了GSS - API安全上下文,并提供可用的安全服务。两个应用程序通过创建和使用 GSSContext 对象来建立和维护构成安全上下文的共享信息。

1.1 上下文建立前的准备

若使用默认的 GSSManager 实例来实例化 GSSContext ,则可保证使用Kerberos V5 GSS - API机制进行上下文建立。该机制由Oid “1.2.840.113554.1.2.2” 标识,在RFC 1964中定义。

在上下文建立阶段开始前,上下文发起者可以请求建立的上下文具有特定的特性,示例代码如下:

// Instantiate and initialize a security con
// established with the server
GSSContext context = manager.createContext(serverName, 
    krb5Mechanism, userCreds, GSSContext.DEFAULT_LIFETIME);
// t desired context options prior to context 
// tablishment
context.requestConf(true);
context.requestMutualAuth(true);
context.requestReplayDet(true);
context.requestSequenceDet(true);

不过,并非所有底层机制都支持调用者可能期望的所有特性。上下文建立后,调用者可以使用各种查询方法检查该上下文提供的特性和服务。

1.2 上下文建立过程

上下文建立是在一个循环中进行的,发起者(如客户端)调用 initSecContext ,接受者(如服务器)调用 acceptSecContext ,直到上下文建立完成。在上下文建立阶段,可以调用 isProtReady 方法来确定上下文是否可用于尚未完全建立的逐消息操作。当 isProtReady 方法返回 true 时,可以使用查询例程来确定已建立上下文的特性和服务。

1.3 消息安全

MessageProp 实用类用于在逐消息操作中传达逐消息属性。在使用 GSSContext 接口的 wrap getMIC 方法时,使用该类的实例来指示所需的保护质量(QOP),并指定是否对调用者提供的数据应用保密服务(仅适用于 wrap 方法)。若要请求默认QOP,应使用值 0 。示例代码如下:

// perform wrap on an application-supplied message, appMsg,
// using QOP = 0, and requesting privacy service
MessageProp mProp = new MessageProp(0, true);
byte[] tok = context.wrap(appMsg, 0, appMsg.length, mProp);
sendToken(tok);

应用程序还可以开始使用 wrap getMIC 逐消息方法对应用程序提供的数据进行加密操作,然后将结果令牌发送给与之建立了安全上下文的其他应用程序。接收者调用 unwrap verifyMIC 方法来解释每个令牌。当上下文不再需要时,应用程序应调用 dispose 方法释放上下文可能使用的任何系统资源。

2. JSSE核心类与机制

JSSE(Java Secure Socket Extension)为Java应用程序提供了身份验证、机密性和完整性控制,以保护通信对等方之间传递的数据免受未经授权的披露和篡改。其核心类位于 javax.net javax.net.ssl 包中。

2.1 建立SSL上下文

SSLSocket 可以通过 SSLSocketFactory 创建,也可以由 SSLServerSocket 接受入站连接时创建。而 SSLSocketFactory SSLServerSocketFactory 对象由 SSLContext 创建。

建立SSL上下文有两种主要方法:
- 使用默认方法 :调用 SSLSocketFactory SSLServerSocketFactory 的静态 getDefault 方法,创建一个具有默认 KeyManager TrustManager 和安全随机数生成器的默认 SSLContext 。对于Sun的JSSE实现,使用的密钥材料位于默认的密钥库/信任库中。
- 自定义方法 :调用 SSLContext 的静态 getInstance 方法获取实例,然后通过 init 方法初始化。 init 方法接受三个参数: KeyManager 对象数组、 TrustManager 对象数组和一个随机数生成器。示例代码如下:

SSLContext sc = SSLContext.getInstance("SSL");
sc.init(km, tm, random);

一旦建立了SSL连接,就会创建一个 SSLSession ,其中包含各种信息,如已建立的身份、使用的密码套件等。该会话用于描述两个实体之间正在进行的关系和状态信息。

2.2 SocketFactory和ServerSocketFactory类

javax.net.SocketFactory 抽象类用于创建套接字,其他工厂类必须继承该类,以创建特定的套接子类别,从而为套接字创建提供通用框架。 javax.net.ServerSocketFactory 类专门用于创建服务器套接字。

使用套接字工厂的优点如下:
- 由于工厂和套接字的多态性,同一应用程序代码可以通过传递不同类型的工厂来使用各种类型的套接字。
- 工厂本身可以使用套接字构造中使用的参数进行自定义,例如返回具有各种网络超时或安全参数的套接字。
- 返回给应用程序的套接字可以是 java.net.Socket (或 javax.net.ssl.SSLSocket )的子类,以便直接公开新的API,如压缩、安全、记录标记、统计信息收集或防火墙隧道等功能。

获取 SSLSocket 实例有两种方式:
- 通过 SSLSocketFactory createSocket 方法创建。
- 通过 SSLServerSocket accept 方法获取。

以下是获取 SSLSocketFactory 的三种主要方式:
1. 调用 SSLSocketFactory.getDefault 静态方法获取默认工厂。
2. 作为API参数接收工厂,例如 javax.net.ssl.HttpsURLConnection setDefaultSSLSocketFactory setSSLSocketFactory 方法。
3. 构造具有特定配置行为的新工厂。

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;

    A([开始]):::startend --> B{选择获取方式}:::decision
    B -->|默认方法| C(调用getDefault方法):::process
    B -->|API参数| D(接收工厂作为参数):::process
    B -->|自定义构造| E(构造新工厂):::process
    C --> F(获取默认SSLSocketFactory):::process
    D --> F
    E --> F
    F --> G([结束]):::startend
3. SSLSocket和SSLServerSocket类

javax.net.ssl.SSLSocket 类继承自 java.net.Socket 类,支持所有标准套接字方法,并添加了特定于安全套接字的方法。该类的实例封装了创建它们的 SSLContext 。虽然有API可以控制套接字实例的安全套接字会话的创建,但信任和密钥管理并不直接暴露。

javax.net.ssl.SSLServerSocket 类类似于 SSLSocket 类,专门用于创建服务器套接字。

4. 其他JSSE相关类
4.1 SSLSession接口

javax.net.ssl.SSLSession 表示在 SSLSocket 连接的两个对等方之间协商的安全上下文。假设对等方共享兼容的 SSLContext 数据,一旦安排好会话,未来在相同两个对等方之间连接的 SSLSocket 可以共享该会话。会话包含将用于安全套接字通信的密码套件,以及对远程对等方网络地址的非权威性提示和管理信息,如创建时间和最后使用时间。

4.2 HttpsURLConnection类

HTTPS协议类似于HTTP,但在请求/接收数据之前先通过SSL/TLS套接字建立安全通道。 javax.net.ssl.HttpsURLConnection 类扩展了 java.net.HttpsURLConnection 类,添加了对HTTPS特定功能的支持。

在获取 HttpsURLConnection 后,可以配置一些HTTP/HTTPS网络连接参数,例如:
- 设置分配的 HostnameVerifier :如果URL的主机名与在SSL/TLS握手期间收到的凭据中的主机名不匹配,可能发生了URL欺骗。如果实现无法确定主机名匹配,则SSL实现将回调实例分配的 HostnameVerifier 进行进一步检查。
- 设置分配的 SSLSocketFactory :在某些情况下,需要指定 HttpsURLConnection 实例使用的 SSLSocketFactory 。可以通过 setDefaultSSLSocketFactory 方法设置默认工厂,也可以通过 setSSLSocketFactory 方法为特定实例设置工厂。

4.3 SunJSSE提供者

Sun Microsystems的JSSE版本标配了一个名为Sun - JSSE的提供者。该提供者包提供以下服务:
| 服务类型 | 具体服务 |
| ---- | ---- |
| 密钥工厂实现 | 支持RSA算法 |
| 密钥对生成器 | 生成适用于RSA算法的公钥和私钥对 |
| 密钥库 | 支持PKCS12 |
| 数字签名算法 | 支持MD2withRSA、MD5withRSA和SHA1withRSA |
| 密钥管理器和信任管理器工厂 | 处理X.509证书 |
| SSLContext实现 | 支持SSL、SSLv3、TLS和TLSv1协议 |

4.4 SSLContext类

javax.net.ssl.SSLContext 是一个引擎类,其实例充当SSL套接字工厂的工厂。 SSLContext 保存了在该上下文下创建的所有套接字共享的所有状态信息。每个实例通过其 init 方法使用执行身份验证所需的密钥、证书链和受信任的根CA证书进行配置。

创建 SSLContext 对象的步骤如下:
1. 使用 SSLContext 类的 getInstance 工厂方法创建实例,需要指定协议名称,也可以指定提供者:

public static SSLContext getInstance(String protocol);
public static SSLContext getInstance(String protocol, String provider);
public static SSLContext getInstance(String protocol, Provider provider);
  1. 调用 init 方法初始化:
public void init(KeyManager[] km, TrustManager[] tm, SecureRandom random);

如果 KeyManager[] 参数为 null ,将为该上下文定义一个空的 KeyManager 。如果 TrustManager[] 参数为 null ,将搜索已安装的安全提供者以获取 TrustManagerFactory 的最高优先级实现,并从中获取适当的 TrustManager 。随机数生成器参数可以为 null ,此时将使用默认实现。

4.5 TrustManager接口

javax.net.ssl.TrustManager 的主要职责是确定是否应信任呈现的身份验证凭据。如果凭据不可信,连接将被终止。要对安全套接字的远程身份进行身份验证,需要使用一个或多个 TrustManager 初始化 SSLContext 对象,为每个支持的身份验证机制传递一个 TrustManager 。如果在 SSLContext 初始化时传递 null ,将为你创建一个信任管理器。通常, SSLContext 有一个单一的信任管理器,并且该信任管理器通常支持基于X.509公钥证书的身份验证。

5. Java GSS - API中的委托权限

在Java GSS - API中, DelegationPermission 用于控制凭据的委托。当一个主体需要代表另一个主体向服务器进行操作时,就需要相应的委托权限。

DelegationPermission 的目标是一个由两个字符串组成的字符串,用于指定服务主体。创建 DelegationPermission 实例时,内部的引号需要用 \ 进行转义。示例代码如下:

DelegationPermission permission = new DelegationPermission(
    "\"ftp@EXAMPLE.COM\" \"krbtgt/EXAMPLE.COM@EXAMPLE.COM\"");

上述代码创建的权限允许Kerberos服务主体 ftp@EXAMPLE.COM 接收由 krbtgt/EXAMPLE.COM@EXAMPLE.COM 表示的转发TGT(Ticket Granting Ticket)。与无条件的转发TGT不同,使用两个主体名称的权限允许更细粒度的委托,例如特定服务的代理票据。

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;

    A([开始]):::startend --> B(创建DelegationPermission实例):::process
    B --> C(指定服务主体字符串):::process
    C --> D(转义内部引号):::process
    D --> E(完成权限创建):::process
    E --> F([结束]):::startend
6. 上下文特性请求与检查

在使用Java GSS - API建立安全上下文之前,上下文发起者可以请求特定的上下文特性。以下是一些常见的特性请求示例:

// Instantiate and initialize a security con
// established with the server
GSSContext context = manager.createContext(serverName, 
    krb5Mechanism, userCreds, GSSContext.DEFAULT_LIFETIME);
// t desired context options prior to context 
// tablishment
context.requestConf(true); // 请求机密性
context.requestMutualAuth(true); // 请求相互认证
context.requestReplayDet(true); // 请求重放检测
context.requestSequenceDet(true); // 请求序列检测

然而,并非所有底层机制都支持所有请求的特性。在上下文建立后,调用者可以使用各种查询方法检查上下文实际提供的特性和服务。例如:

if (context.isProtReady()) {
    boolean isConfSupported = context.getConfState();
    boolean isMutualAuthSupported = context.getMutualAuthState();
    boolean isReplayDetSupported = context.getReplayDetState();
    boolean isSequenceDetSupported = context.getSequenceDetState();
}
7. JSSE中的套接字工厂使用场景

在实际应用中,不同的场景可能需要不同的套接字工厂配置。以下是一些常见的使用场景及对应的操作步骤:

7.1 使用默认套接字工厂

当应用程序对安全上下文的配置要求不高,希望使用默认的安全设置时,可以使用默认的套接字工厂。操作步骤如下:
1. 获取默认的 SSLSocketFactory

SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
  1. 使用工厂创建 SSLSocket
SSLSocket socket = (SSLSocket) factory.createSocket("example.com", 443);
7.2 自定义套接字工厂

当应用程序需要特定的安全配置,如自定义的密钥管理器、信任管理器或随机数生成器时,可以自定义 SSLSocketFactory 。操作步骤如下:
1. 创建 SSLContext 实例:

SSLContext context = SSLContext.getInstance("TLS");
  1. 初始化 SSLContext
KeyManager[] km = ...; // 自定义密钥管理器
TrustManager[] tm = ...; // 自定义信任管理器
SecureRandom random = ...; // 自定义随机数生成器
context.init(km, tm, random);
  1. 获取自定义的 SSLSocketFactory
SSLSocketFactory factory = context.getSocketFactory();
  1. 使用工厂创建 SSLSocket
SSLSocket socket = (SSLSocket) factory.createSocket("example.com", 443);
7.3 通过API参数传递套接字工厂

当代码需要创建套接字,但不关心套接字的具体配置时,可以通过API参数接收 SSLSocketFactory 。例如,在 javax.net.ssl.HttpsURLConnection 中:

SSLSocketFactory customFactory = ...; // 自定义的SSLSocketFactory
HttpsURLConnection connection = (HttpsURLConnection) new URL("https://example.com").openConnection();
connection.setSSLSocketFactory(customFactory);
8. SSLSession的复用与管理

SSLSession 可以在多个 SSLSocket 连接之间复用,从而提高性能和效率。当两个对等方建立了一个 SSLSession 后,后续的连接可以尝试复用该会话。以下是一个简单的示例:

SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket socket1 = (SSLSocket) factory.createSocket("example.com", 443);
SSLSession session1 = socket1.getSession();

// 后续连接尝试复用会话
SSLSocket socket2 = (SSLSocket) factory.createSocket("example.com", 443);
socket2.setUseClientMode(true);
socket2.startHandshake();
SSLSession session2 = socket2.getSession();

if (session1.getId().equals(session2.getId())) {
    System.out.println("Session复用成功");
} else {
    System.out.println("Session复用失败");
}

在管理 SSLSession 时,需要注意以下几点:
- 会话的有效性:会话有一定的生命周期,超过有效期后将无法复用。
- 会话的共享:只有在相同的 SSLContext 下创建的套接字才能共享会话。
- 会话的安全性:复用会话时,需要确保会话的安全性,避免会话劫持等安全问题。

9. HttpsURLConnection的配置要点

在使用 HttpsURLConnection 时,正确的配置可以提高连接的安全性和可靠性。以下是一些配置要点及对应的操作步骤:

9.1 设置HostnameVerifier

为了防止URL欺骗,需要设置合适的 HostnameVerifier 。操作步骤如下:
1. 创建自定义的 HostnameVerifier

HostnameVerifier verifier = new HostnameVerifier() {
    @Override
    public boolean verify(String hostname, SSLSession session) {
        // 自定义主机名验证逻辑
        return hostname.equals("example.com");
    }
};
  1. HostnameVerifier 应用到 HttpsURLConnection
HttpsURLConnection connection = (HttpsURLConnection) new URL("https://example.com").openConnection();
connection.setHostnameVerifier(verifier);
9.2 设置SSLSocketFactory

在某些情况下,需要指定 HttpsURLConnection 使用的 SSLSocketFactory 。操作步骤如下:
1. 获取或创建自定义的 SSLSocketFactory

SSLSocketFactory factory = ...; // 自定义的SSLSocketFactory
  1. SSLSocketFactory 应用到 HttpsURLConnection
HttpsURLConnection connection = (HttpsURLConnection) new URL("https://example.com").openConnection();
connection.setSSLSocketFactory(factory);
10. 总结

Java平台提供了丰富的安全机制,包括Java GSS - API和JSSE,用于保护应用程序之间的通信安全。通过合理使用这些机制,可以实现身份验证、机密性、完整性保护和凭据委托等功能。

在实际应用中,需要根据具体的需求选择合适的安全机制和配置。例如,在需要细粒度的权限控制时,可以使用 DelegationPermission ;在建立安全连接时,可以根据不同的场景选择合适的套接字工厂和配置 SSLSession 。同时,要注意安全配置的正确性和安全性,避免出现安全漏洞。

以下是一个简单的总结表格:
| 安全机制 | 主要功能 | 关键类 |
| ---- | ---- | ---- |
| Java GSS - API | 建立安全上下文,实现消息安全 | GSSContext MessageProp DelegationPermission |
| JSSE | 提供身份验证、机密性和完整性控制 | SSLContext SSLSocketFactory SSLSession |

通过深入理解和掌握这些安全机制,开发者可以更好地保护Java应用程序的通信安全,为用户提供更安全可靠的服务。

【无人机】基于改进粒子群算法的无人机路径规划研究[和遗传算法、粒子群算法进行比较](Matlab代码实现)内容概要:本文围绕基于改进粒子群算法的无人机路径规划展开研究,重点探讨了在复杂环境中利用改进粒子群算法(PSO)实现无人机三维路径规划的方法,并将其遗传算法(GA)、标准粒子群算法等传统优化算法进行对比分析。研究内容涵盖路径规划的多目标优化、避障策略、航路点约束以及算法收敛性和寻优能力的评估,所有实验均通过Matlab代码实现,提供了完整的仿真验证流程。文章还提到了多种智能优化算法在无人机路径规划中的应用比较,突出了改进PSO在收敛速度和全局寻优方面的优势。; 适合人群:具备一定Matlab编程基础和优化算法知识的研究生、科研人员及从事无人机路径规划、智能优化算法研究的相关技术人员。; 使用场景及目标:①用于无人机在复杂地形或动态环境下的三维路径规划仿真研究;②比较不同智能优化算法(如PSO、GA、蚁群算法、RRT等)在路径规划中的性能差异;③为多目标优化问题提供算法选型和改进思路。; 阅读建议:建议读者结合文中提供的Matlab代码进行实践操作,重点关注算法的参数设置、适应度函数设计及路径约束处理方式,同时可参考文中提到的多种算法对比思路,拓展到其他智能优化算法的研究改进中。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值