2013-09-24 31 views
6

Tôi có một ứng dụng web đặt bối cảnh bảo mật mùa xuân thông qua bộ lọc lò xo. Dịch vụ được bảo vệ bằng chú thích mùa xuân dựa trên vai trò của người dùng. Những công việc này.Làm thế nào để tuyên truyền bối cảnh an ninh mùa xuân cho JMS?

Tác vụ không đồng bộ được thực hiện trong trình lắng nghe JMS (mở rộng javax.jms.MessageListener). Thiết lập của người nghe này được thực hiện với Spring.

Tin nhắn được gửi từ ứng dụng web, tại thời điểm này người dùng được xác thực. Tôi cần xác thực giống nhau trong chuỗi JMS (người dùng và vai trò) trong quá trình xử lý tin nhắn.

Hôm nay này được thực hiện bằng cách đặt xác thực mùa xuân trong JMS ObjectMessage:

SecurityContext context = SecurityContextHolder.getContext(); 
Authentication auth = context.getAuthentication(); 
... put the auth object in jms message object 

Sau đó, bên trong người nghe JMS đối tượng xác thực được chiết xuất và thiết lập trong bối cảnh:

SecurityContext context = new SecurityContextImpl(); 
context.setAuthentication(auth); 
SecurityContextHolder.setContext(context); 

tác phẩm này hầu hết thời gian. Nhưng khi có sự chậm trễ trước khi xử lý tin nhắn, tin nhắn sẽ không bao giờ được xử lý. Tôi không thể xác định được nguyên nhân của những tin nhắn này bị mất, nhưng tôi không chắc chắn cách chúng tôi tuyên truyền xác thực là tốt, ngay cả khi nó hoạt động trong custer khi thông điệp được xử lý trong máy chủ khác.

Đây có phải là cách phù hợp để tuyên truyền xác thực mùa xuân không?

Kính trọng, Mickaël

+0

Tôi không quen thuộc với Spring trong bối cảnh này, nhưng tôi đã gặp vấn đề này trước đây. Một ngữ cảnh bảo mật tốt sẽ có thời gian hết hạn mà sau đó nó không thể được sử dụng nữa. Nói chung nếu việc gửi tin nhắn bị trì hoãn trong quá hạn, ngữ cảnh bảo mật sẽ hết hạn và tin nhắn không được xử lý. Đây có thể là vấn đề ở đây, trong trường hợp đó tăng thời gian hết hạn có thể khắc phục nó, hoặc ít nhất là làm cho nó ít phổ biến hơn. – Alasdair

Trả lời

0

tôi không tìm thấy giải pháp tốt hơn, nhưng điều này làm việc cho tôi tốt.

Bằng cách gửi tin nhắn JMS, tôi đang lưu trữ Authentication làm Tiêu đề và tương ứng bằng cách nhận lại bối cảnh bảo mật. Để lưu trữ Authentication như Tiêu đề bạn phải serialise nó như Base64:

class AuthenticationSerializer { 

static String serialize(Authentication authentication) { 
    byte[] bytes = SerializationUtils.serialize(authentication); 
    return DatatypeConverter.printBase64Binary(bytes); 
} 

static Authentication deserialize(String authentication) { 
    byte[] decoded = DatatypeConverter.parseBase64Binary(authentication); 
    Authentication auth = (Authentication) SerializationUtils.deserialize(decoded); 
    return auth; 
    } 
} 

Bằng cách gửi chỉ cần đặt tiêu đề tin nhắn - bạn có thể tạo Decorator cho tin nhắn mẫu, do đó nó sẽ xảy ra tự động. Trong trang trí của bạn, bạn chỉ cần gọi phương thức như vậy:

private void attachAuthenticationContext(Message message){ 
    Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 
    String serialized = AuthenticationSerializer.serialize(auth); 
    message.setStringProperty("authcontext", serialized); 
} 

Nhận được phức tạp hơn, nhưng cũng có thể được thực hiện tự động. Thay vì áp dụng @EnableJMS sử dụng sau Cấu hình:

@Configuration 
class JmsBootstrapConfiguration { 

    @Bean(name = JmsListenerConfigUtils.JMS_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME) 
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE) 
    public JmsListenerAnnotationBeanPostProcessor jmsListenerAnnotationProcessor() { 
     return new JmsListenerPostProcessor(); 
    } 

    @Bean(name = JmsListenerConfigUtils.JMS_LISTENER_ENDPOINT_REGISTRY_BEAN_NAME) 
    public JmsListenerEndpointRegistry defaultJmsListenerEndpointRegistry() { 
     return new JmsListenerEndpointRegistry(); 
    } 
} 

class JmsListenerPostProcessor extends JmsListenerAnnotationBeanPostProcessor { 


    @Override 
    protected MethodJmsListenerEndpoint createMethodJmsListenerEndpoint() { 
     return new ListenerEndpoint(); 
    } 

} 

class ListenerEndpoint extends MethodJmsListenerEndpoint { 
    @Override 
    protected MessagingMessageListenerAdapter createMessageListenerInstance() { 
     return new ListenerAdapter(); 
    } 
} 

class ListenerAdapter extends MessagingMessageListenerAdapter { 

    @Override 
    public void onMessage(Message jmsMessage, Session session) throws JMSException { 
     propagateSecurityContext(jmsMessage); 
     super.onMessage(jmsMessage, session); 
    } 

    private void propagateSecurityContext(Message jmsMessage) throws JMSException { 
     String authStr = jmsMessage.getStringProperty("authcontext");   
     Authentication auth = AuthenticationSerializer.deserialize(authStr); 
     SecurityContextHolder.getContext().setAuthentication(auth); 
    }  

} 
1

tôi đã thực hiện cho bản thân mình một giải pháp khác nhau, trong đó có vẻ dễ dàng hơn đối với tôi.

Tôi đã có một trình chuyển đổi tin nhắn, trình chuyển đổi tin nhắn JSON Jackson chuẩn, mà tôi cần phải cấu hình trên JMSTemplate và người nghe.

Vì vậy, tôi đã tạo một triển khai MessageConverter bao quanh một trình chuyển đổi tin nhắn khác và truyền bá bối cảnh bảo mật thông qua các thuộc tính thư JMS. (Trong trường hợp của tôi, ngữ cảnh được truyền là mã thông báo JWT mà tôi có thể trích xuất từ ​​ngữ cảnh hiện tại và áp dụng cho ngữ cảnh bảo mật của chuỗi nghe).

Bằng cách này, toàn bộ trách nhiệm tuyên truyền ngữ cảnh bảo mật được thực hiện một cách trang nhã trong một lớp duy nhất và chỉ yêu cầu một chút cấu hình.

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