2015-11-19 14 views
9

Tôi đã thực hiện cấp phép mật khẩu OAuth2 với mô-đun bảo mật mùa xuân. Tôi thêm thực hiện riêng của UserDetails và UserDetailsService (jdbc). Tôi đưa Người dùng vào bộ điều khiển của mình bằng:Spring Oauth2 - tải lại hiệu trưởng

@AuthenticationPrincipal User user 

nơi Người dùng là người triển khai UserDetails của tôi. Bây giờ tôi muốn thêm khả năng thay đổi dữ liệu Người dùng mà không cần mã thông báo làm mới.

tôi cố gắng để làm mới hiệu trưởng với:

User updatedUser = ... 
Authentication newAuth = new UsernamePasswordAuthenticationToken(updatedUser, updatedUser.getPassword(), updatedUser.getAuthorities()); 
SecurityContextHolder.getContext().setAuthentication(newAuth); 

Nhưng nó không hoạt động, khi tôi gọi một phương pháp điều khiển nó sẽ trả về đối tượng tài khoản cũ.

Có cách nào để thay đổi dữ liệu Người dùng mà không có mã thông báo làm mới không? Có bất kỳ giải pháp nào để bảo mật mùa xuân luôn tải dữ liệu người dùng từ cơ sở dữ liệu (không phải từ Cache) không?

+0

Trong đó lớp của ứng dụng nào bạn làm mới hiệu trưởng? –

Trả lời

2

Tôi đã tìm thấy cách để đạt được điều này từ this answer. Tôi tạo ra HttpSessionSecurityContextRepository

@Bean 
public ReloadUserPerRequestHttpSessionSecurityContextRepository userDetailContextRepository() { 
    return new ReloadUserPerRequestHttpSessionSecurityContextRepository(); 
} 

và thêm video này vào HttpSecurity của tôi từ lớp của WebSecurityConfigurerAdapter như

.and() 
     .csrf() 
      .csrfTokenRepository(csrfTokenRepository()) 
    .and() 
     .securityContext() 
      .securityContextRepository(userDetailContextRepository()) 

Dưới đây là mã mẫu để lấy thông tin người dùng được cập nhật ở mọi yêu cầu. Bạn có thể tìm nạp từ máy chủ API hoặc user-info-url cấu hình oauth2 của mình.

public class ReloadUserPerRequestHttpSessionSecurityContextRepository extends HttpSessionSecurityContextRepository { 

    @Override 
    public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) { 
     SecurityContext context = super.loadContext(requestResponseHolder); 

     Authentication auth = context.getAuthentication(); 
     if (auth != null && auth instanceof OAuth2Authentication) { 
      OAuth2Authentication oldAuth = (OAuth2Authentication) auth; 
      if (oldAuth.getPrincipal() instanceof LinkedHashMap) { 
       createNewUserDetailsFromPrincipal(oldAuth.getPrincipal()); 
      } 
      context.setAuthentication(oldAuth); 
     } 
     return context; 
    } 

    @SuppressWarnings("unchecked") 
    private void createNewUserDetailsFromPrincipal(Object principal) { 
     LinkedHashMap<String, Object> userDetailInfo = (LinkedHashMap<String, Object>) principal; 
     // fetch User informations from your API server or your database or 
     // 'user-info-url' of oauth2 endpoint 
     userDetailInfo.put("name", "EDITED_USER_NAME"); 
    } 

} 
1

Tôi không chắc nhưng đây chỉ là phỏng đoán, tôi nghĩ bạn cũng cần xóa SecurityContext.

Trước bối cảnh an ninh rõ ràng với SecurityContextHolder.clearContext(); sau đó mã của bạn để thiết lập xác thực

Authentication newAuth = new UsernamePasswordAuthenticationToken(updatedUser, updatedUser.getPassword(), updatedUser.getAuthorities()); 
SecurityContextHolder.getContext().setAuthentication(newAuth); 
+0

Các ứng dụng được bảo mật bởi Oauth2 không thể gán với xác thực loại 'UsernamePasswordAuthenticationToken'. – Cataclysm

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