2016-12-11 14 views
6

Tôi có 2 ứng dụng Khởi động mùa xuân riêng biệt, một ứng dụng phục vụ như một máy chủ ủy quyền OAuth 2 và máy chủ khác làm máy chủ tài nguyên. Tôi đang sử dụng số RemoteTokenServices của Spring trong máy chủ tài nguyên của mình để kiểm tra mã thông báo từ máy chủ ủy quyền. Bây giờ, tôi đang cố gắng định nghĩa mã điều khiển được bảo vệ trong ứng dụng máy chủ tài nguyên của mình, nhưng tôi không chắc chắn cách ánh xạ lớp UserDetails tới hiệu trưởng xác thực được cung cấp thông qua cơ chế OAuth 2.Làm cách nào để ánh xạ mã thông báo OAuth 2 tới đối tượng UserDetails trong máy chủ tài nguyên?

Tôi đã thiết lập máy chủ ủy quyền với TokenEnhancer tùy chỉnh bổ sung thêm chi tiết vào mã thông báo sao cho /oauth/check_token?token=<token> trả về với trường tùy chỉnh mà tôi muốn ánh xạ tới bộ điều khiển máy chủ tài nguyên của mình.

Trong một thiết lập nguyên khối nhiều nơi máy chủ uỷ quyền cũng là máy chủ tài nguyên, tôi có thể xác định phương pháp điều khiển mà làm cho việc sử dụng chính xác nhận theo cách này:

//User implements UserDetails 
public Map<String, Object> getResource(@AuthenticationPrincipal User user) { 
    //code that uses the user object 
} 

Tuy nhiên, điều này dường như không làm việc thẳng tiến theo cách tiếp cận phân tán hơn. Ánh xạ không thành công và tham số user kết thúc là đối tượng rỗng. Tôi đã cố gắng sử dụng các phương pháp sau đây:

public Map<String, Object> getResource(Authentication authentication) { 
    //code that uses the authentication object 
} 

Mặc dù mã bản đồ trên thành công các chi tiết xác thực, nó không cung cấp một cách cho tôi để truy cập trực tiếp các lĩnh vực tùy chỉnh tôi đã thiết lập thông qua TokenEnhancer tôi đã đề cập trước đó. Tôi dường như không thể tìm thấy bất cứ điều gì từ tài liệu Spring về vấn đề này.

Trả lời

8

Để giải quyết vấn đề, trước tiên, hãy để tôi trải qua một chút kiến ​​trúc nền. Đối tượng UserDetails được ánh xạ tự động qua @AuthenticationPrincipal xuất phát từ trường principal của đối tượng đang hoạt động Authentication. Bộ điều khiển máy chủ tài nguyên có quyền truy cập vào đối tượng OAuth2Authencation, là một cá thể chuyên biệt của Authentication cho khung bảo mật Spring OAuth2, chỉ bằng cách tuyên bố nó như một phần của tham số phương thức.

public void controllerMethod(OAuth2Authentication authentication) { 
    //controller definition 
} 

Biết được điều này, vấn đề bây giờ chuyển sang làm thế nào để chắc chắn rằng getPrincipal() phương pháp trong đối tượng Authentication là một thể hiện của lớp tùy chỉnh UserDetails tôi. RemoteTokenServices Tôi sử dụng trong ứng dụng máy chủ tài nguyên sử dụng một phiên bản AccessTokenConverter để hiểu chi tiết mã thông báo được gửi bởi máy chủ ủy quyền. Theo mặc định, nó sử dụng DefaultAccessTokenConverter, mà chỉ đặt hiệu trưởng xác thực làm tên người dùng, là String. Bộ chuyển đổi này sử dụng UserAuthenticationConverter để chuyển đổi dữ liệu đến từ máy chủ ủy quyền thành một phiên bản Authentication. Đây là những gì tôi cần để tùy chỉnh:

DefaultAccessTokenConverter tokenConverter = new DefaultAccessTokenConverter(); 
tokenConverter.setUserTokenConverter(new DefaultUserAuthenticationConverter() { 

    @Override 
    public Authentication extractAuthentication(Map<String, ?> map) { 
     Authentication authentication = super.extractAuthentication(map); 
     // User is my custom UserDetails class 
     User user = new User(); 
     user.setSpecialKey(map.get("specialKey").toString()); 
     return new UsernamePasswordAuthenticationToken(user, 
       authentication.getCredentials(), authentication.getAuthorities()); 
    } 

}); 
tokenServices.setAccessTokenConverter(tokenConverter); 

Với tất cả các thiết lập này, cơ chế @AuthenticationPrincipal hiện hoạt động như mong đợi.

+0

Giải pháp này hoạt động, nhưng nó là một giải pháp thay vì sửa lỗi. Lý do bạn nhận được String for Principle là vì userDetailsService không được tiêm đúng vào DefaultUserAuthenticationConverter(). Bây giờ câu hỏi là nó cần phải được tiêm ở đâu để giải pháp này không cần thiết? – zalis

0

Bạn đã bật AuthenticationPrincipalArgumentResolver, như sau xml?

<mvc:annotation-driven> 
     <mvc:argument-resolvers> 
       <bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" /> 
     </mvc:argument-resolvers> 
</mvc:annotation-driven> 

Và bạn cần phải thực hiện các UserDetails trở về của riêng bạn CustomerUser object, sau đó bạn có thể sử dụng chú thích để có được chính trực tiếp.

+0

Tôi chưa bao giờ phải xác định rõ ràng điều đó. Tôi nghĩ rằng trình phân giải đã là một phần của cấu hình tự động của Spring Boot. –

+0

@PsychoPunch Đó là. – chrylis

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