2015-03-06 13 views
9

Tôi đang cố gắng thay đổi một ứng dụng từ việc sử dụng java7u51 sang java8u40 nhưng xác thực SSO không thành công. Khách hàng không thay đổi, nó sử dụng các cuộc gọi Windows JNA (Secur32.INSTANCE.InitializeSecurityContext) nhưng máy chủ không còn chấp nhận vé nữa. Mã máy chủ không thay đổi nhưng nó đang sử dụng các thư viện java chuẩn dường như đã thay đổi. Máy chủ chạy dưới Linux.Thay đổi xác thực phía máy chủ Kerberos/SPNEGO trong Java8

Mã máy chủ bên dưới. Trên máy tính cửa sổ của tôi, tôi viết một tệp chứa vé để tôi có thể chạy mã bên dưới để thử nghiệm. Tôi có một bộ đồng hồ rất cao để tôi có thể kiểm tra vé. Tôi đã viết các khách hàng vé bằng cách sử dụng java7u51 chỉ trong trường hợp nhưng điều đó đã không giúp đỡ. Cùng một vé hoạt động tốt khi tôi chạy mã máy chủ dưới đây trong java7.

Lỗi không thành công là isEstablished trả về giá trị sai. Không có thông tin gỡ lỗi hữu ích. isEstablished trả về false ngụ ý rằng có nhiều vòng cần thiết hơn nhưng đó không phải là trường hợp, và tôi không nghĩ rằng nó nên được.

Có ai biết lý do điều này hiện không thành công trong java8 không? Nó không chỉ là một vấn đề cập nhật 40, nó không thành công với phiên bản java 8 trước đó.

nhờ

Properties.setProp("sun.security.krb5.debug", "true") 
Properties.setProp("java.security.krb5.realm", "xxxx") 
Properties.setProp("java.security.krb5.kdc", "xxxx") 
Properties.setProp("java.security.krb5.conf", url(getClass, "/krb5.conf.auth").toExternalForm) 
Properties.setProp("java.security.auth.login.config", url(getClass, "/jaas.conf.auth").toExternalForm) 
Properties.setProp("javax.security.auth.useSubjectCredsOnly", "true") 

val loginCtx: LoginContext = new LoginContext("Server", new LoginCallbackHandler(password)) 
loginCtx.login() 
val subject = loginCtx.getSubject 
val ticket = StringIO.readStringFromFile(new File("/tmp/ticket")) 
val decoder: BASE64Decoder = new BASE64Decoder 
val serviceTicket = decoder.decodeBuffer(ticket) 

val user = Subject.doAs(subject, new PrivilegedAction[Option[String]]() { 
    def run = { 
    try { 
     val manager = GSSManager.getInstance 
     val context: GSSContext = manager.createContext(null: GSSCredential) 
     val arrayOfBytes = context.acceptSecContext(serviceTicket, 0, serviceTicket.length) 
     // we ignore arrayOfBytes 
     assert(context.isEstablished, "Failed to establish context: " + context) 
     val username = context.getSrcName.toString 
     Some(username) 
    } catch { 
     case e: Exception => 
     println("failed: " + e.getMessage) 
     None 
    } 
    } 
}) 

krb5.conf.auth 
[libdefaults] 
default_realm = XXX 
allow_weak_crypto=true 
default_tkt_enctypes = rc4-hmac des-cbc-md5 des-cbc-crc des3-cbc-sha1 
default_tgs_enctypes = rc4-hmac des-cbc-md5 des-cbc-crc des3-cbc-sha1 
permitted_enctypes = rc4-hmac des-cbc-md5 des-cbc-crc des3-cbc-sha1 
default_checksum = rsa-md5 
kdc_timesync = 0 
kdc_default_options = 0x40000010 
clockskew = 30000 
check_delegate = 0 
ccache_type = 3 
kdc_timeout = 60000 
forwardable = true 
dns_lookup_realm = true 
dns_lookup_kdc = true 
ticket_lifetime = 24h 

#excluding realms and domain_realm 

jaas.conf.auth (server section) 

Server { 
    com.sun.security.auth.module.Krb5LoginModule required 
    useKeyTab=false 
    debug=true 
    isInitiator=false 
    storeKey=true 
    useTicketCache=false 
    principal="XXX"; 
}; 

Cập nhật: Trong trường hợp này giúp. Tôi nghĩ rằng khách hàng đang gửi một vé SPNEGO, bởi vì nếu tôi cố gắng buộc bối cảnh chỉ chấp nhận Kerberos (1.2.840.113554.1.2.2) tôi nhận được lỗi failed: No credential found for: 1.3.6.1.5.5.2 usage: Accept

Cập nhật 2: Đây không thực sự là câu trả lời , nhưng nếu tôi thay đổi cách cửa sổ máy khách tạo ra vé nó hoạt động. Vì vậy, nếu thay vì tạo ra một vé SPNEGO bọc bạn tạo một vé chỉ Kerberos nó được chấp nhận bởi Java8. Vì vậy, việc thay đổi "Thương lượng" thành "Kerberos" bên dưới sẽ khắc phục được sự cố.

Secur32.INSTANCE.AcquireCredentialsHandle(
     servicePrincipalName, 
     "Negotiate", // Change to "Kerberos" 
     new NativeLong(Sspi.SECPKG_CRED_OUTBOUND), 
     null, 
     authIdentity.getPointer, 
     null, 
     null, 
     phClientCredential, 
     ptsClientExpiry) 
+0

Hãy thử sử dụng "NTLM" thay vì "Thương lượng" và cho tôi biết liệu nó có hoạt động hay không. Tôi đã có vấn đề tương tự. – kukis

+0

Có phải java8 có thể thả hỗ trợ cho 'allow_weak_crypto = true' không? –

+0

Java 8 đã thay đổi mặc định cho allow_weak_crypto thành false, vì vậy bạn không thể sử dụng DES trừ khi được chỉ định rõ ràng là đúng: https://docs.oracle.com/javase/8/docs/technotes/guides/security/enhancements-8 .html –

Trả lời

1

Kerberos/Spnego là một lĩnh vực chất thải ..

Từ những gì nói đến cái tâm của tôi, dưới đây là một danh sách kiểm tra nhanh chóng mà hy vọng sẽ giúp đỡ bất kỳ.

  1. Bạn có tạo lại thẻ khóa của mình không? với cùng một JDK mà bạn đang sử dụng ở phía máy chủ?
  2. Máy chủ của bạn có đang chạy đúng người dùng (như được định nghĩa trong tab chính) không?
  3. Bạn đã tạo cho họ lựa chọn tùy chọn "không bao giờ hết hạn"?
  4. Bạn có yêu cầu mã hóa 256 bit không? có thể được nhìn thấy cách gõ (loại chìa khóa 18 = AES-256):

    % JAVA_HOME% \ bin \ klist -e -f -a -k XX.keytab

    %JAVA_HOME%\bin\klist -e -f -a -k XX.keytab]

    Nếu vậy, có bạn thêm unrestricted policy fileslocal_policy.jar US_export_policy.jar trong% JAVA_HOME% \ jre \ lib \ security? Đảm bảo giá trị KVNO giống nhau trong danh sách bạn nhận được. Lý tưởng nhất, bạn sẽ chỉ thấy một đầu ra.

  5. SPN của bạn có thể ping được không?

  6. Danh sách máy chủ KDC của bạn có chính xác không?
  7. Chú ý đến krb5.conf. Có vấn đề với. Dường như là trường hợp nhạy cảm ngay cả trong môi trường Windows.

Có thể khó thiết lập Kerberos. Vậy thì chúc may mắn.

Các vấn đề liên quan