2012-05-07 38 views
10

Tôi đã cấu hình bảo mật mùa xuân bằng máy chủ ldap (nhưng tiếp tục đọc, không có vấn đề gì nếu bạn không biết gì về nó, đây thực sự là vấn đề về mùa xuân). Tất cả chạy như một say mê. Dưới đây là những dòng tôi sử dụng cho rằng:Mùa xuân, tập tin bất động sản, giá trị rỗng

<ldap-server ldif="" root="" manager-dn="" manager-password="" url="" id="ldapServer" /> 

Nếu tôi điền LDIF và rễ thuộc tính, nó sẽ chạy một máy chủ embeded:

<ldap-server ldif="classpath://ldap.ldif" root="dc=springframework,dc=org" manager-dn="" manager-password="" url="" id="ldapServer" /> 

Nếu tôi điền vào các lĩnh vực khác, nó sẽ chạy một máy chủ ở xa :

<ldap-server ldif="" root="" manager-dn="dc=admin,dc=springframeworg,dc=org" manager-password="password" url="ldap://myldapserver.com/dc=springframeworg,dc=org" id="ldapServer" /> 

Tất cả nội dung này chạy đúng cách. Bây giờ tôi muốn sử dụng cơ chế mùa xuân để tải các thông số như vậy từ một tập tin bất động sản:

Vì vậy, tôi thay thế cho giá trị thuộc tính như thế này:

<ldap-server ldif="${ldap.ldif.path}" root="${ldap.ldif.root}" manager-dn="${ldap.server.manager.dn}" manager-password="${ldap.server.manager.password}" url="${ldap.server.url}" id="ldapServer" /> 

và tạo ra một tập tin bất động sản với:

ldap.server.url= 
ldap.server.manager.dn= 
ldap.server.manager.password= 

ldap.ldif.path= 
ldap.ldif.root= 

Bây giờ , phần thú vị của vấn đề. Nếu tôi điền vào các thuộc tính sau trong tệp:

ldap.server.url=ldap://myldapserver.com/dc=springframeworg,dc=org 
ldap.server.manager.dn=dc=admin,dc=springframeworg,dc=org 
ldap.server.manager.password=password 

ldap.ldif.path= 
ldap.ldif.root= 

Nó chạy máy chủ ở xa như mong đợi.

Nếu tôi điền vào các tập tin bất động sản như thế này:

ldap.server.url= 
ldap.server.manager.dn= 
ldap.server.manager.password= 

ldap.ldif.path= classpath:ldap.ldif 
ldap.ldif.root= dc=springframeworg,dc=org 

Nó không chạy, phàn nàn rằng url ldap là mất tích. Nhưng vấn đề là nếu tôi thay đổi cấu hình mùa xuân từ:

<ldap-server ldif="${ldap.ldif.path}" root="${ldap.ldif.root}" manager-dn="${ldap.server.manager.dn}" manager-password="${ldap.server.manager.password}" url="${ldap.server.url}" id="ldapServer" /> 

đến (bằng cách chỉ cần loại bỏ các tham chiếu đến biến $ {} ldap.server.url)

<ldap-server ldif="${ldap.ldif.path}" root="${ldap.ldif.root}" manager-dn="${ldap.server.manager.dn}" manager-password="${ldap.server.manager.password}" url="" id="ldapServer" /> 

Nó chạy!

Mặc dù của tôi là mùa xuân không thay thế giá trị thuộc tính bằng thuộc tính cấu hình một nếu thuộc tính này trống. Nhưng tôi thấy nó lạ.

Bạn có thể cho tôi một số đầu mối để hiểu điều đó không? Và cách tốt nhất để cấu hình máy chủ ldap của tôi thông qua một tệp thuộc tính là gì?

EDIT: điều này là do một sự lựa chọn thiết kế nghèo (nhìn vào câu trả lời được chấp nhận), một vấn đề đã được khai trương vào ngày jira: https://jira.springsource.org/browse/SEC-1966

+0

Bạn sử dụng phiên bản Spring nào? – Roadrunner

+0

Đây là 3.0.5.RELEASE –

Trả lời

2

Ok, tôi nghĩ đây là lỗi bảo mật mùa xuân.

Nếu tôi gỡ lỗi và xem xét lớp LdapServerBeanDefinition, có một phương thức được gọi là "phân tích cú pháp". Đây là một trích xuất:

public BeanDefinition parse(Element elt, ParserContext parserContext) { 
    String url = elt.getAttribute(ATT_URL); 

    RootBeanDefinition contextSource; 

    if (!StringUtils.hasText(url)) { 
     contextSource = createEmbeddedServer(elt, parserContext); 
    } else { 
     contextSource = new RootBeanDefinition(); 
     contextSource.setBeanClassName(CONTEXT_SOURCE_CLASS); 
     contextSource.getConstructorArgumentValues().addIndexedArgumentValue(0, url); 
    } 

    contextSource.setSource(parserContext.extractSource(elt)); 

    String managerDn = elt.getAttribute(ATT_PRINCIPAL); 
    String managerPassword = elt.getAttribute(ATT_PASSWORD); 

    if (StringUtils.hasText(managerDn)) { 
     if(!StringUtils.hasText(managerPassword)) { 
      parserContext.getReaderContext().error("You must specify the " + ATT_PASSWORD + 
        " if you supply a " + managerDn, elt); 
     } 

     contextSource.getPropertyValues().addPropertyValue("userDn", managerDn); 
     contextSource.getPropertyValues().addPropertyValue("password", managerPassword); 
    } 

    ... 
} 

Nếu tôi gỡ lỗi ở đây, tất cả các biến (url, managerDn, managerPassword ...) không được thay thế bằng giá trị được chỉ định trong tệp thuộc tính. Và như vậy, url có giá trị $ {ldap.server.url}, managerDn có giá trị $ {ldap.server.manager.dn} và cứ thế.

Phương thức phân tích cú pháp tạo một bean, một nguồn ngữ cảnh sẽ được sử dụng thêm. Và khi đậu này sẽ được sử dụng, người giữ chỗ sẽ được thay thế.

Ở đây, chúng tôi đã nhận được lỗi. Kiểm tra phương thức phân tích cú pháp nếu url trống hay không. Vấn đề là url không rỗng ở đây vì nó có giá trị $ {ldap.server.url}. Vì vậy, phương thức phân tích cú pháp tạo ra một nguồn ngữ cảnh như một máy chủ ở xa.

Khi nguồn được tạo sẽ được sử dụng, nó sẽ thay thế $ {ldap.server.url} theo giá trị trống (như được chỉ định trong tệp thuộc tính). Và ....... Bug!

Tôi không biết thực sự giải quyết vấn đề này như thế nào, nhưng bây giờ tôi đã hiểu tại sao lỗi này xảy ra;)

+0

Đây không phải là lỗi. Thuộc tính url không nên được sử dụng nếu bạn định tạo máy chủ nhúng. Xem http://static.springsource.org/spring-security/site/docs/3.1.x/reference/ldap.html#ldap-server – Ritesh

+0

Điều tôi gọi là lỗi là sử dụng chuỗi rỗng chạy và sử dụng biến không chạy vì kiểm tra bảo mật mùa xuân rằng url không rỗng bởi không thay thế biến bằng giá trị của nó (có thể trống!). Đây là một thiết kế kém. –

+1

Trong trường hợp đó, tôi nghĩ có thể báo cáo vấn đề trong trình theo dõi lỗi mùa xuân, đúng không? https://jira.springsource.org/secure/Dashboard.jspa –

1

Tôi không thể giải thích nó, nhưng tôi nghĩ bạn có thể khắc phục vấn đề của bạn sử dụng cú pháp mặc định, có sẵn từ Spring 3.0.0.RC1 (see).

Trong chageg đăng nhập của bạn có thể đọc: PropertyPlaceholderConfigurer hỗ trợ "$ {MyKey: myDefaultValue}" mặc định cú pháp

Dù sao, tôi nghĩ rằng vấn đề là vì "" là giá trị hợp lệ, nhưng không có giá trị trong file tài sản không.

+0

cảm ơn câu trả lời, nhưng tôi đã luôn luôn lỗi tương tự bằng cách sử dụng mẹo giá trị mặc định. –

+0

Tôi không hiểu. Nếu giá trị mặc định là '', tôi cho rằng nó nên giống với giá trị mặc định ''. – jddsantaella

+0

Vâng, tôi cũng nghĩ vậy ... Nó rất lạ ... Có lẽ, setter của url được gọi chỉ khi chúng ta sử dụng một biểu thức mùa xuân, và gọi setter với một giá trị rỗng gây ra lỗi. Trong trường hợp không chỉ định biểu thức, setter có thể không được gọi? –

1

Tôi nghĩ rằng url="" công trình vì url thuộc tính là loại xs:token trong XSD mùa xuân-an ninh và chuỗi rỗng được chuyển thành null (xs:token là loại bỏ bất kỳ dấu cách ở đầu hoặc cuối, vì vậy "" có thể được công nhận là không có giá trị). Có lẽ giá trị của ${ldap.server.url} được giải quyết dưới dạng chuỗi trống và đó là lý do bạn gặp lỗi.

Bạn có thể thử sử dụng hồ sơ Xuân để xác định cấu hình khác nhau của máy chủ ldap (xem Spring Team Blog để biết chi tiết về cấu hình)

+1

LdapServerBeanDefinitionParser đã và đang chăm sóc nó. Bằng cách nào đó, nó đã quản lý để tạo ra định nghĩa bean của org.springframework.security.ldap.DefaultSpringSecurityContextSource với URL trống trong hàm tạo mặc dù tất cả các kiểm tra dường như được đặt ra để ngăn chặn nó. – Ritesh

+1

Tôi nghĩ rằng tôi đã tìm thấy lý do tại sao Ritesh có quyền và tại sao nó không chạy: Khi tôi gỡ lỗi sự ra mắt của máy chủ (trong phân tích cú pháp của LdapServerBeanDefinition), tất cả các trình giữ chỗ không được thay thế. Vì vậy, url là: $ {ldap.server.url}. Độ phân giải của trình giữ chỗ được thực hiện sau khi tạo nguồn ngữ cảnh. –

+0

Theo tài liệu http://static.springsource.org/spring-security/site/docs/3.1.x/reference/ldap.html#ldap-server, thuộc tính url không nên được sử dụng nếu chúng tôi muốn tạo máy chủ nhúng. – Ritesh

1

Tôi tin rằng có một vấn đề ở đây trong khi sử dụng giữ chỗ. Sau đây nhất có thể sẽ giải quyết vấn đề:

Tạo lớp mở rộng PropertyPlaceHolderConfigurer và ghi đè phương thức convertPropertyValue() vào phương pháp bạn có thể trả về thuộc tính dưới dạng chuỗi rỗng nếu bạn tìm thấy bất kỳ thứ gì ngoài chuỗi LDAP url tức là ldap: //myldapserver.com/dc=springframeworg,dc=org

Ngoài ra, bạn cần phải định cấu hình chuyên môn mới của lớp PropertyPlaceHolderConfigurer trong tệp ngữ cảnh.

Hy vọng điều này sẽ hữu ích.

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