首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

Java SE 6 網絡編程新特性深度解析:NTLM 認證、輕量級 HTTP Server、Cookie 管理與國際化域名

     編輯:Java 程式設計入門

Java SE 6 在網絡編程領域引入重量級增強,圍繞 HTTP 協議提供企業級認證支援、嵌入式 HTTP 服務、標準化 Cookie 管理、增強型網絡介面檢測與國際化域名 (IDN) 支援。本文逐項深度解析並提供實戰代碼。

1. NTLM 認證:Windows 域環境集成

背景痛點

  • Java 6 前無原生 NTLM 支援,訪問 IIS/SharePoint/Exchange 需手工實作協議或依賴第三方庫
  • 基本認證 (Base64 編碼用戶名密碼) 傳輸不安全,Digest 認證部署複雜

NTLM 協議流程

  1. 客戶端將密碼哈希化為 NTLM Hash
  2. 發送用戶名 (明文) 給服務器
  3. 服務器返回 16 位隨機 Challenge
  4. 客戶端用 NTLM Hash 加密 Challenge 返回 Response
  5. 服務器轉發給域控制器 (DC) 驗證
  6. DC 用用戶 Hash 加密 Challenge 比對,一致則認證通過

Java 6 實作代碼

import java.net.*;

public class NtlmAuthenticator extends Authenticator {
    private final String username;
    private final String domain;
    private final String password;
    
    public NtlmAuthenticator(String domain, String username, String password) {
        this.domain = domain;
        this.username = username;
        this.password = password;
    }
    
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        // 格式:DOMAIN/username
        String credential = domain + "/" + username;
        return new PasswordAuthentication(credential, password.toCharArray());
    }
}

// 使用方式
Authenticator.setDefault(new NtlmAuthenticator("CORP", "admin", "secret123"));

URL url = new URL("https://sharepoint.corp.intra/sites/team");
URLConnection conn = url.openConnection();
// 透明觸發 NTLM 握手
InputStream in = conn.getInputStream();

系統屬性簡化配置

設定 http.auth.ntlm.domain=CORP 後,getPasswordAuthentication() 僅需返回用戶名密碼,框架自動拼接域前綴。

認證協商順序

GSS/SPNEGO (Kerberos) → Digest → NTLM → Basic
  • IIS 同時支援 Negotiate (Kerberos) 與 NTLM
  • Java 6 自動協商,客戶端無感知
  • GSS/SPNEGO 底層基於 JAAS + Kerberos

2. 輕量級 HTTP 服務器:com.sun.net.httpserver

核心 API

  • HttpServerProvider:SPI 提供者,獲取實現
  • HttpServer:服務器實例,綁定端口、註冊上下文
  • HttpContext:路徑映射 (如 /myapp/)
  • HttpHandler:請求處理介面 handle(HttpExchange)
  • HttpExchange:封裝請求/響應、輸入輸出流、Headers

完整示例:50 行構建 REST 端點

import com.sun.net.httpserver.*;
import java.io.*;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

public class MiniHttpServer {
    public static void main(String[] args) throws IOException {
        HttpServer server = HttpServer.create(new InetSocketAddress(7778), 0);
        
        // 註冊上下文
        server.createContext("/api/hello", exchange -> {
            String response = "{\"message\":\"Hello, Java SE 6 HTTP Server!\"}";
            exchange.getResponseHeaders().set("Content-Type", "application/json; charset=UTF-8");
            exchange.sendResponseHeaders(200, response.getBytes("UTF-8").length);
            try (OutputStream os = exchange.getResponseBody()) {
                os.write(response.getBytes("UTF-8"));
            }
        });
        
        server.createContext("/api/echo", exchange -> {
            String method = exchange.getRequestMethod();
            String body = new String(exchange.getRequestBody().readAllBytes(), "UTF-8");
            String response = String.format("{\"method\":\"%s\",\"body\":\"%s\"}", method, body);
            exchange.sendResponseHeaders(200, response.getBytes("UTF-8").length);
            try (OutputStream os = exchange.getResponseBody()) {
                os.write(response.getBytes("UTF-8"));
            }
        });
        
        server.setExecutor(Executors.newCachedThreadPool());
        server.start();
        System.out.println("HTTP Server started on port 7778");
        System.out.println("GET  https://localhost:7778/api/hello");
        System.out.println("POST https://localhost:7778/api/echo");
    }
}

適用場景

  • 單元/整合測試 Mock 服務
  • 嵌入式設備管理介面
  • 輕量級微服務原型、Webhook 接收器
  • 無需引入 Jetty/Tomcat 依賴的簡易 HTTP 端點

3. 標準化 Cookie 管理:java.net.CookieManager

核心類結構

CookieHandler (抽象基類)
    └── CookieManager (預設實現)
            ├── CookieStore (存儲/檢索) → 内存實現 / 持久化實現
            └── CookiePolicy (接受策略) → ACCEPT_ALL / ACCEPT_NONE / ACCEPT_ORIGINAL_SERVER

關鍵類功能

類/介面核心職責
HttpCookie封裝 Cookie 屬性:name、value、domain、path、maxAge、secure、httpOnly、version (支援 Netscape/RFC2109/RFC2965)
CookieStoreadd(URI, HttpCookie)、get(URI)、getCookies()、getURIs()、自動清理過期 Cookie
CookiePolicyshouldAccept(URI, HttpCookie) 判定是否接受
CookieManager整合 Store + Policy,實現 CookieHandler 契約

實戰代碼:客戶端 Cookie 自動管理

import java.net.*;
import java.util.List;

public class CookieDemo {
    public static void main(String[] args) throws Exception {
        // 1. 建立自定義 Manager:接受所有 Cookie
        CookieManager manager = new CookieManager();
        manager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
        CookieHandler.setDefault(manager); // 設為全域預設
        
        // 2. 模擬首次請求:Server 返回 Set-Cookie
        URL url = new URL("https://httpbin.org/cookies/set/sessionid/abc123");
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.getInputStream().close(); // 觸發請求,Cookie 自動存入 Store
        
        // 3. 後續請求:自動攜帶 Cookie
        URL url2 = new URL("https://httpbin.org/cookies");
        HttpURLConnection conn2 = (HttpURLConnection) url2.openConnection();
        try (BufferedReader br = new BufferedReader(
                new InputStreamReader(conn2.getInputStream()))) {
            System.out.println("Server 回應 (含自動攜帶 Cookie):");
            String line;
            while ((line = br.readLine()) != null) System.out.println(line);
        }
        
        // 4. 程式化操作 Cookie Store
        CookieStore store = manager.getCookieStore();
        for (URI uri : store.getURIs()) {
            System.out.println("Domain: " + uri.getHost());
            for (HttpCookie cookie : store.get(uri)) {
                System.out.printf("  %s=%s [Path:%s, MaxAge:%d, Secure:%b]%n",
                    cookie.getName(), cookie.getValue(), cookie.getPath(), 
                    cookie.getMaxAge(), cookie.getSecure());
            }
        }
    }
}

4. NetworkInterface 增強:網絡介面深度檢測

Java SE 6 新增實用方法:

方法返回值用途
isUp()boolean介面啟動且運行中
isLoopback()boolean回環介面 (127.0.0.1)
isPointToPoint()boolean點對點鏈路 (PPP/VPN)
supportsMulticast()boolean支援多播 (IGMP)
getHardwareAddress()byte[]MAC 位址 (6 bytes)
getMTU()int最大傳輸單元 (通常 1500)
isVirtual()boolean虛擬介面 (Docker/VM/Hyper-V)

掃描所有非回環、啟動介面的 MAC 位址

NetworkInterface.getNetworkInterfaces().asIterator()
    .forEachRemaining(ni -> {
        try {
            if (ni.isUp() && !ni.isLoopback() && ni.getHardwareAddress() != null) {
                String mac = bytesToHex(ni.getHardwareAddress());
                System.out.printf("%s: %s (MTU:%d, Virtual:%b)%n",
                    ni.getDisplayName(), mac, ni.getMTU(), ni.isVirtual());
            }
        } catch (SocketException e) { e.printStackTrace(); }
    });

5. 國際化域名 (IDN) 支援:java.net.IDN

RFC 3490/5890 定義 Unicode 域名轉 ASCII (Punycode) 算法:

import java.net.IDN;

public class IdnDemo {
    public static void main(String[] args) {
        String unicodeDomain = "例子.测试"; // 中文域名
        String asciiDomain = IDN.toASCII(unicodeDomain); 
        // 輸出: xn--fsq092a.xn--0zwm56d
        
        String recovered = IDN.toUnicode(asciiDomain);
        // 輸出: 例子.测试
        
        System.out.println("Unicode: " + unicodeDomain);
        System.out.println("ASCII (Punycode): " + asciiDomain);
        System.out.println("Recovered: " + recovered);
        
        // 驗證合法性
        try {
            IDN.toASCII("invalid..domain"); // 拋出 IllegalArgumentException
        } catch (IllegalArgumentException e) {
            System.out.println("非法域名格式");
        }
    }
}

版本演進總結表

特性Java 5Java 6Java 7+
NTLM 認證不支援原生支援增強 (SPNEGO/Kerberos 更穩)
HTTP Server無com.sun.net.httpserver標準化 (JEP 274 jdk.httpserver)
Cookie 管理僅抽象類完整實現持久化 Store (File/DB)
NetworkInterface基礎枚舉狀態/屬性檢測更多硬體屬性
IDN無toASCII/toUnicodeUTS #46 相容

總結

Java SE 6 的網絡增強解決了企業級集成中的三大痛點:Windows 域認證互操作、零依賴 HTTP 端點構建、標準化會話狀態管理。配合網絡介面深度檢測與國際化域名支援,使 Java 成為真正的「網絡編程第一方語言」。現代項目雖多遷移至 Java 11/17/21,但這些 API 設計哲學與核心類結構延續至今,深入理解其機制仍是高階網絡編程的必修課。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved