2012-09-26 60 views
5

Cách thích hợp để bảo mật số @RequestBody với Bảo mật mùa xuân là gì?Bảo mật mùa xuân @RequestBody

Ví dụ: A User có thể có nhiều Blog s và mỗi Blog có thể có nhiều Entry s. Một người sử dụng đi để lưu một mục vào một blog nào đó và yêu cầu sẽ đến trong như thế này:

@RequestMapping(value="/api/entry", method=RequestMethod.POST) 
@ResponseBody 
public Entry save(@Valid @RequestBody Entry entry) { 
    this.entryService.save(entry); 
    return entry; 
} 

Bây giờ, đến entryBlog, người dùng có thể giả mạo lên yêu cầu và lựa chọn trên blog của người khác, đăng một cách hiệu quả mục nhập vào blog của họ. Mặc dù tôi có thể nắm bắt điều này trong xác nhận (truy vấn lớp kiên trì để xác minh rằng Blog thuộc về đăng nhập User) Tôi cảm thấy rằng điều này sẽ được xử lý bởi Spring Security. Nếu vậy, làm thế nào để tôi đi về việc này?

Trả lời

6

Chúng tôi có loại tình huống này.

Đây là hai giải pháp. Tôi không thích nhiều

@RequestMapping(value="/api/entry", method=RequestMethod.POST) 
@ResponseBody 
@PreAuthorize("#entry.author.name == principal.name)" 
public Entry save(@Valid @RequestBody Entry entry, Principal principal) { 
    this.entryService.save(entry); 
    return entry; 
} 

hoặc

@RequestMapping(value="/api/entry", method=RequestMethod.POST) 
    @ResponseBody 
    @PreAuthorize("Decision.isOK(entry, principal)") 
    public Entry save(@Valid @RequestBody Entry entry, Principal principal) { 
     this.entryService.save(entry); 
     return entry; 
    } 

// Trong trường hợp đó, mùa xuân sẽ gọi phương thức tĩnh của bạn isOk() từ Quyết định lớp. Nó sẽ trả về boolean.

Tiêm mùa xuân Đối tượng chính được ủy quyền chính cho phương pháp này, bạn không phải lo lắng về điều đó. Enable @PreAuthorize chú thích với

<security:global-method-security pre-post-annotations="enabled" />

Second Sử dụng Aspect. Tạo khía cạnh.

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) 
public @interface Protector { 
} 

@Aspect 
@Component 
public class MyAspect { 
    @Before("@annotation(com.xyz.Protector)") 
    public void before(JoinPoint joinPoint) throws Throwable { 
     //u can get method object from joinPoint object, 
     Method method = ((MethodSignature)joinPoint.getMethodSignature()).getMethod(); 
     //As long as you have Method object you can read the parameter objects (Entry and Principal) with reflection. 
     //So Compare here: If entry.getOwner().getId().equal(principal.getName()) blah blah blah 
    } 
} 

@RequestMapping(value="/api/entry", method=RequestMethod.POST) 
@ResponseBody 
@Protector 
public Entry save(@Valid @RequestBody Entry entry, Principal principal) { 
    this.entryService.save(entry); 
    return entry; 
} 

Nếu bạn có khía cạnh bạn có thể có nhiều sở hữu trên runtime

Cũng tham khảo này ulr

+1

Sau khi thử cả hai phương pháp tôi đã hạnh phúc nhất với '@ PreAuthorize'. Đối với bất cứ ai khác đi qua này, đảm bảo cơ thể req là hơi phức tạp đối với tôi và tôi đã có thể dây lên một hạt với một số dịch vụ. EL thay đổi một chút khi gọi một cá thể bean. Ví dụ: '@PreAuthorize (" @ decision.isOK (# entry.blog.id, hiệu trưởng) ")' –

+1

Tôi rất vui vì nó đã giúp :) '@ PreAuthorize' là chính xác cho mục đích này, trong khi @Aspect là tổng quát hơn:) – Elbek

+0

Tham số phương thức tham chiếu từ một Spring-EL trong @PreAuthorize nên được thêm tiền tố với một '' '' # '' ''. '' '' @PreAuthorize ("Decision.isOK (#entry, #principal)") '' '' thay vì '' '' @PreAuthorize ("Decision.isOK (mục, hiệu trưởng)") '' ''. –

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